You are on page 1of 7

Lebanese University

Lab 1 PIPE
Computer Systems II – I3303
Dr. Jacques Demerjian

Exercise 1: Write a C program that contains a producer process (reads from the stdin and
write to a pipe) and a consumer process that makes capital letter the small letter (reads
from the pipe and writes to the stdout).

#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<fcntl.h>

#define BUFSIZE 256

int main(){
int fd[2];
int pid, nbRead;
char c;
char buf1[BUFSIZE],buf2[BUFSIZE];
pipe(fd);
pid=fork();

if(pid!=0){
close(fd[0]);
while(nbRead=read(STDIN_FILENO,buf1,BUFSIZE)){
write(fd[1],buf1,nbRead);
}
close(fd[1]);
}else{
close(fd[1]);
while(nbRead=read(fd[0],&c,1)){
c=toupper(c);
write(STDOUT_FILENO,&c,nbRead);
}
close(fd[0]);
exit(0);
}
return 0;
}
Exercise 2: Write a C program that creates 2 processes A and B that can communicate via
a pipe. The process "A" open a file given by argument to the program and transfers the
content of the file to process B via the pipe. The process "B" write the content of the pipe
to a second file given also by argument. Verify if the first file have the default permissions
0644.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFSIZE 256
void Copying(int , int , char *);
int main(int argc, char*argv[]) {
char buf1[BUFSIZE] ;
char buf2[BUFSIZE] ;
int childpid;
int fd1;
int fd2;
int fd[2];
int i;
char* fsrc;
char* fdest;
struct stat infofile1;

if(argc!=3)
{
fprintf(stderr, "Usage error");
exit(1);
}

fsrc=argv[1];
fdest=argv[2];

fd1=open(fsrc, O_RDONLY);
if(fd1==-1)
{
perror("open:");
exit(1);
}
fstat(fd1,&infofile1);
printf("mode=%d \n",infofile1.st_mode);
if(infofile1.st_mode==0100644)
{
printf("Default permissions\n");
}
if (pipe(fd) == -1)
{
perror("Failed to create the pipe");
exit(1); }
childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
exit(1);
}

if (childpid!=0) {
//------ parent code ------//
close(fd[0]);
Copying(fd1,fd[1],buf1);
close(fd[1]);
close(fd1);
if(wait(NULL))
{
fprintf(stderr, "--child finished--");
}
fprintf(stderr,"--Bye in parent--");
}
else
{
//--------child code------//
close(fd[1]);
fd2=open(fdest,O_CREAT | O_WRONLY,0600);
if(fd2==-1)
{
perror("open:");
exit(1);
}
Copying(fd[0],fd2,buf2);

close(fd2);
close(fd[0]);

fprintf(stderr,"--Bye in child--");
exit(0);
}

return 0;
}
void Copying(int in, int out, char *buf){
int nbRead;
while(1)
{
nbRead=read(in, buf, BUFSIZE);
fprintf(stderr,"reading...");
if(nbRead==-1)
{
perror("read:");
exit(1);
}
if(nbRead==0)
{
fprintf(stderr, "--end reading--");
break;
}
write(out,buf,nbRead);
}
}
/*NB:
it is important to close the writer on the pipe (before the wait) so the reader will
return 0 and knows that we arrive to the EOF. because an EOF is not transmitted in the
pipe.
When a process calls read on a pipe, the read returns immediately if the pipe is not
empty. If the pipe is empty, the read blocks until something is written to the pipe, as
long as some process has the pipe open for writing. On the other hand, if no process
has the pipe open for writing, a read from an empty pipe returns 0, indicating an end-
of-file condition. (This description assumes that access to the pipe uses blocking I/O.)
*/
Exercise 3: Write a C program that is equivalent to the shell command
ps aux | grep root | wc -l

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>

int main(){
int fd1[2], fd2[2];
int pid1, pid2;

pipe(fd1);
pid1=fork();
if(pid1!=0){
close(fd1[0]);
dup2(fd1[1],1);
execlp("ps","ps","aux",NULL);
perror("ps");
exit(1);
}else{
close(fd1[1]);
pipe(fd2);
pid2=fork();
if(pid2!=0){
close(fd2[0]);
dup2(fd1[0],0);
dup2(fd2[1],1);
execlp("grep","grep","root",NULL);
perror("grep");
exit(1);
}else{
close(fd2[1]);
dup2(fd2[0],0);
execlp("wc","wc","-l",NULL);
perror("wc");
exit(1);
}
}

return 0;
}
Exercise 4: Write a program that creates a ring of 3 processes connected by pipes.
– The first process should ask the user for a string and then send it to the second
process.
– The second process should reverse the string and send it to the third process.
– The third process should convert the string to uppercase and send it back to the
first process.
• When the first process gets the processed string, it should display it to the terminal.
• When this is done, all 3 processes should terminate.
• Here's an illustration of the process ring:

• Here's an example of the program in action:


$ ring ...run the program.
Please enter a string: ole
Processed string is: ELO
$_

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#define BUFSIZE 256
void reverseLine(char *,int);
int main(){
int pid1, pid2;
char buf1[BUFSIZE],buf2[BUFSIZE],buf3[BUFSIZE],buf4[BUFSIZE];
int fd1[2],fd2[2],fd3[2];
int i,nbRead, nbRead1;
pipe(fd1); pipe(fd2);pipe(fd3);

pid1=fork();
if(pid1!=0){//Parent
pid2=fork();
if(pid2!=0){//Parent
close(fd1[0]);
close(fd3[1]);
close(fd2[0]);
close(fd2[1]);
while(nbRead=read(STDIN_FILENO,buf1,BUFSIZE)){
write(fd1[1],buf1,nbRead);
nbRead1=read(fd3[0],buf4,BUFSIZE);
write(STDOUT_FILENO,buf4,nbRead1);
}
//close descriptors;
close(fd1[1]);
close(fd3[0]);
while(wait(NULL)>0);
exit(0);
}else{//Child2
close(fd1[0]);
close(fd1[1]);
close(fd2[1]);
close(fd3[0]);
while(nbRead=read(fd2[0],buf3,BUFSIZE)){
for(i=0;i<nbRead;i++){
buf3[i]=toupper(buf3[i]);
}
write(fd3[1],buf3,nbRead);
}
close(fd3[1]);
close(fd2[0]);
exit(0);
}
}else{//child1
close(fd3[0]);
close(fd3[1]);
close(fd1[1]);
close(fd2[0]);
while(nbRead=read(fd1[0],buf2,BUFSIZE)){
reverseLine(buf2,nbRead-1);
write(fd2[1],buf2,nbRead);
}
close(fd1[0]);
close(fd2[1]);
exit(0);
}
return 0;
}
void reverseLine(char *buffer,int n){
int i;
char tmp;
for(i=0;i<n/2;i++){
tmp=buffer[i];
buffer[i]=buffer[n-i-1];
buffer[n-i-1]=tmp;
}
}

You might also like