Links Powered by MicMac
Cocoa-C-Porting
Fink's translation team
Mac OSX, Fink and Unix
Client/Server Architecture
PowerPC Architecture - UML
System programming
Merise
Pierre-Loïc and Pascaline's wedding

Programming System 05

Last modified: 22/04/2004 05:29:13 CEST
Author: Michèle Garoche contact

Contents - Process scheduling - Fork and Wait - Pthread and Exec - Exec - Pipes - Message queues - Memory management - Paging and segmentation - Synchronization (1) - Synchronization (2) - File System Management - Socket Programming (1) - Revision

Programming System

Pipes

Tutorial class by Philippe Décogné

22/11/2002 (dd/mm/yy)

Unnamed pipes

Pipes characteristics

Caption

Progsys 05-01

Creation of a pipe

Pipe: int pipe(int *fildes)

Creates an object allowing a unidirectional data flow and allocates a pair of file descriptors: the first one connects to the read end of the pipe, the second one to the write end. Returns -1 if it fails, otherwise 0.

Library to be used: unistd.h

Man page: pipe(2) - system calls.

Caption

Progsys 05-02

Reading from the pipe

nb_read = read(p[0]), buf, SIZE_BUF);

If the pipe is not empty, the read command reads at most SIZE_BUF characters.

If the pipe is empty:

Writing into the pipe

nb_written = write(p[1], buf, n);

If nb_written = 0, then the process receives a SIGPIPE signal, which kills the process. Then the pipe becomes a so called broken pipe.

If the number of writers is not null and if reading is blocking, then the process is suspended until writing is finished.

If reading is non blocking:

Problem 1

Write a program where a parent creates a child. Both communicate via two unnamed pipes. The parent process sends a message to the child, which answers it.

Caption

(none)

Solution

Basics

The process creates two pipes, then forks a child. Hence the pipes are duplicated. Closing appropriate read and write ends of both pipes in each process creates a two-way flow of data between parent and child.

Parent process before the fork

Progsys 05-07

Parent and child processes just after the fork

Progsys 05-08

Parent and child processes after closing appropriate ends of pipes

Progsys 05-09

Program pipessai.c

/* pipessai.c

A child sends a message to its parent via a pipe. The parent answers the message by another message. */

/* Includes */
#include <stdio.h>        /* for access to the standard i/o files, printf */
#include <unistd.h>       /* for fork, read, close */
#include <sys/wait.h>     /* for wait */
#include <stdlib.h>       /* for exit, EXIT_SUCCESS, EXIT_FAILURE */
#include <string.h>       /* for strerror */
#include <sys/errno.h>    /* for ECHILD*/

/* Defines */
#define HELLO "Hello child!"
#define BONJOUR "Bonjour père !"

/* Extern global variables */
extern int errno;

int main()
{
  /* Variables */
  int pipestatus1, pipestatus2;  /* return from pipe */
  int pipe1[2], pipe2[2];          /* pointers to file descriptors for pipe */
  int  numbread1, numbread2; /* number of read bytes returned from read */
  ssize_t write1, write2;        /* number of written bytes returned by write */
  int closestatus1, closestatus2;         /* return from close */
  int status;              /* returned when the child process terminates */
  int pid;                   /* returned from fork */
  int waitsignal;            /* returned from wait */
  char buf1[sizeof(HELLO)], buf2[sizeof(BONJOUR)];   /* buffer for bytes stream */

  /* Create the pipes */
  pipestatus1 = pipe(pipe1);

  /* Pipe fails */
  if (pipestatus1 == -1)
    {
      printf("Error while creating the first pipe: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  pipestatus2 = pipe(pipe2);

  /* Pipe fails */
  if (pipestatus2 == -1)
    {
      printf("Error while creating the second pipe: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  /* Create a child process */
  pid = (int)fork();
  /* Fork fails */
  if (pid == -1)
    {
      printf("Error while creating the child process: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  /* Fork succeeds, Child process */
  else if (pid == 0)
    {
      /* Close the read end of pipe2 */
      closestatus2 = close(pipe2[0]);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing the read end of pipe2: %s.\n", strerror(errno));
	}
	
      /* Close the write end of pipe1 */
      if (close(pipe1[1]) == -1)
	  {
		  printf("Error while closing the write end of pipe1 in child: %s.\n", strerror(errno));
	  }
	  
      /* Read the message from pipe1 */
      numbread1 = read(pipe1[0], buf1, sizeof(buf1));

      /* Read fails */
      if (numbread1 == -1)
	{
	  printf("Error while reading from pipe1: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* End of file encountered while reading from pipe1 */
      else if (numbread1 == 0)
	{
	  printf("End of file encountered while reading from pipe1.\n");
	  exit(EXIT_FAILURE);
	}
	
    /* Number of bytes incorrect while reading from pipe1 */
      else if (numbread1 != sizeof(HELLO))
	{
	  printf("Number of bytes incorrect while reading from pipe1.\n");
	  exit(EXIT_FAILURE);
	}

      /* Read succeeds */
      else
	{
	  printf("%s\n", buf1);
	}
		       
      /* Write the message into pipe2 */
      write2 = write(pipe2[1], BONJOUR, sizeof(BONJOUR));

    if (write2 == -1)
	{
	  printf("Error while writing into pipe2: %s\n", strerror(errno));
	}
	else if (write2 != sizeof(BONJOUR))
	{
		printf("Number of bytes written into pipe2 incorrect\n");
		exit(EXIT_FAILURE);
	}

      /* End of child process */
      exit(EXIT_SUCCESS);
    }

  /* Parent process */
  else
    {
      /* Close the read end of pipe1 */
      closestatus1 = close(pipe1[0]);

      /* Close fails */
      if (closestatus1 == -1)
	{
	  printf("Error while closing the read end of pipe1: %s.\n", strerror(errno));
	}
	
    /* Close the write end of pipe2 */
    if (close(pipe2[1]) == -1)
	{
	  printf("Error while closing the write end of pipe2 in parent: %s.\n", strerror(errno));
	} 

    /* Write the message into pipe1 */
    write1 = write(pipe1[1], HELLO, sizeof(HELLO));

    /* Write fails */
    if (write1 == -1)
	{
	  printf("Error while writing into pipe1: %s\n", strerror(errno));
	}
	else if (write1 != sizeof(HELLO))
	{
		printf("Number of bytes written into pipe1 incorrect");
		exit(EXIT_FAILURE);
	}

      /* Wait for the child process terminating */
      waitsignal = wait(&status);

      /* No child process */
      if (waitsignal == -1 && errno == ECHILD)
	{
	  printf("No child process awaiting.\n");
	}

      /* Wait fails */
      else if (waitsignal ==  -1 && errno != ECHILD)
	{
	  printf("Wait failed: %s.\n", strerror(errno));
	}
      else
	{
	  /* Read the message from pipe2 */
	  numbread2 = read(pipe2[0], buf2, sizeof(buf2));

	  /* Read fails */
	  if (numbread2 == -1)
	    {
	      printf("Error while reading from pipe2: %s.\n", strerror(errno));
	      exit(EXIT_FAILURE);
	    }

	  /* End of file encountered */
	  else if (numbread2 == 0)
	    {
	      printf("End of file encountered while reading from pipe2.\n");
	    }
	    
	  /* Number of bytes read from pipe2 incorrect */
	  else if (numbread2 != sizeof(BONJOUR))
	    {
	      printf("Number of bytes read from pipe2 incorrect.\n");
	    }
		       
	  /* Print the message from pipe1 */
	  printf("%s\n", buf2);

	  /* Close the pipes */
	  closestatus1 =  close(pipe1[1]);
	  /* Close fails */
	  if (closestatus1 == -1)
	    {
	      printf("Error while closing the write  end of pipe1: %s.\n", strerror(errno));
	    }     
	  closestatus2 = close(pipe2[1]);
	  /* Close fails */
	  if (closestatus2 == -1)
	    {
	      printf("Error while closing the write  end of pipe2: %s.\n", strerror(errno));
	    }
	}
    }
  return 0;
}

Problem 3

Program the command ps -e | wc -l which counts the numbers of lines the command ps -e returns. This command displays information about the current processes of the current user.

Solution

Primitive to be used

Dup: int dup(int oldd)

Duplicates an existing descriptor and returns its value to the calling process. The argument oldd corresponds to the entry index in the descriptor table. Its value should be less than the table size. The value returned is the lowest numbered descriptor not in use by the process.

Returns -1 if it fails.

Allows to redirect inputs and outputs if the standard input and output descriptors are closed beforehand.

Library to be used: unistd.h

Man page: dup(2) - system calls.

Caption

Progsys 05-04

Program pswcessai.c

/* pswcessai.c

Purpose: Creates a tool which executes ps -e | wc -l.

/* Includes */
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/* Global variables */
extern int errno;

int main(void)
{
  pid_t child1_pid; /* pid of the child process */
  int dup1; /* return from dup */
  int pipestatus; /* return from pipe */
  int pip[2]; /* pipes */
  int closestatus; /* return from close */

  /* Create the pipes */
  if ((pipestatus = pipe(pip)) == -1)
  {
	  printf("Error while creating the pipe: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
  }
  
  /*Create the child process */
  child1_pid = fork();
  if ((int)child1_pid == -1)
  {
      printf("Error in creation of child process: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }
  else if ((int)child1_pid == 0)
    {
      /* Close stdout */
      if ((closestatus = close(STDOUT_FILENO)) == -1)
	  {
		  printf("Error while closing stdout: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Redirect pip[1] */
      if ((dup1 = dup(pip[1])) == -1)
	  {
		  printf("Error while redirecting pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[1] */
      if ((closestatus = close(pip[1])) == -1)
	  {
		  printf("Error while closing pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[0] */
      if ((closestatus = close(pip[0])) == -1)
	  {
		  printf("Error while closing pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }
	  
      /* Execute the command */
	  execlp("ps", "ps", "-e", NULL);

	  /* If the program goes here, call to execlp has failed */
	  printf("Error while executing the command ps -e: %s\n", strerror(errno));
	  exit(EXIT_FAILURE);
    }
  else
    {
      /* Close stdin */
      if ((closestatus = close(STDIN_FILENO)) == -1)
	  {
		  printf("Error while closing stdin: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Redirect pip[0] */
      if ((dup1 = dup(pip[0])) == -1)
	  {
		  printf("Error while redirecting pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[0] */
      if ((closestatus = close(pip[0])) == -1)
	  {
		  printf("Error while closing pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[1] */
      if ((closestatus = close(pip[1])) == -1)
	  {
		  printf("Error while closing pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }
	  
	  printf("Warning:\nas wc -l counts the lines in the pipe, it counts the command ps -e\nas a line. Then as ps always displays a header line, this line is\nalso counted. Therefore, you have to subtract 2 to the result to\nretrieve the number of process.\n"); 

      /* Exec the command */
      execlp("wc", "wc", "-l", NULL);

      /* Exec fails */
      printf("Error while executing the command wc -l: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
	}
	  
  return 0;
}

Variations on pipes

First program

/* pipeessai1.c

Program to run the command:ps -alxjww | sort -k 15 -k 2 -k 3 -k 10 -k 1
which gives the following information about process:

	UID, PID, PPID, CPU, PRI, NI, VSZ, RSS, WCHAN, STAT,
	TT, TIME, USER, PGID, SESS, JOBC, COMMAND

and sorts it by: 

	SESS, PID, PPID, STAT, UID
	
Use pipes and dup */

/* Includes */
#include <stdio.h>        /* for access to the standard i/o files, printf */
#include <unistd.h>       /* for fork, read, close, pipe, dup */
#include <sys/wait.h>     /* for wait */
#include <stdlib.h>       /* for exit, EXIT_SUCCESS, EXIT_FAILURE */
#include <string.h>       /* for strerror */
#include <sys/errno.h>    /* for ECHILD*/

/* Extern global variables */
extern int errno;

int main()
{
  /* Variables */
  int pipestatus;    /* return from pipe */
  int pip[2];        /* pointers to file descriptors for pipe */
  int dup1;          /* return from dup */
  int closestatus2;  /* return from close */
  int pid;           /* returned from fork */


  /* Create the pipes */
  pipestatus = pipe(pip);

  /* Pipe fails */
  if (pipestatus == -1)
    {
      printf("Error while creating the pipe: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  /* Create a child process */
  pid = (int)fork();
  /* Fork fails */
  if (pid == -1)
    {
      printf("Error while creating the child process: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  /* Fork succeeds, Child process */
  else if (pid == 0)
    {
      /* Close stdout */
      closestatus2 = close(STDOUT_FILENO);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing stdout: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Redirect pip[1] */
      dup1 = dup(pip[1]);

      /* Dup fails */
      if (dup1 == -1)
	{
	  printf("Error while redirecting pip[1]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Close pip[1] */
      closestatus2 = close(pip[1]);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing pip[1]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Close pip[0] */
      closestatus2 = close(pip[0]);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing pip[0]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Exec the command */
      execlp("ps", "ps", "-alxjww", NULL);

      /* Exec fails */
      printf("Error while executing the command ps: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

  /* Parent process */
  else
    {
      /* Close stdin */
      closestatus2 = close(STDIN_FILENO);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing stdin: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Redirect pip[0] */
      dup1 = dup(pip[0]);

      /* Dup fails */
      if (dup1 == -1)
	{
	  printf("Error while redirecting pip[0]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Close pip[0] */
      closestatus2 = close(pip[0]);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing pip[0]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Close pip[1] */
      closestatus2 = close(pip[1]);

      /* Close fails */
      if (closestatus2 == -1)
	{
	  printf("Error while closing pip[1]: %s.\n", strerror(errno));
	  exit(EXIT_FAILURE);
	}

      /* Exec the command */
      execlp("sort", "sort", "-k", "15", "-k", "2", "-k", "3", "-k", "10", "-k", "1", NULL);

      /* Exec fails */
      printf("Error while executing the command sort: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
    }
  return 0;
}

Second program

/* finklistsection.c

Purpose: Creates one process which executes fink list --section=whatever_you_choose, 
             then pipes the result with more in parent process. Use dup to clone the pipe.

/* Includes */
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

/* Define */
/* Define the path for fink command - Change it if you don't use the default path */
#define FINK_PATH "/sw/bin/fink"
#define nb_section 22

/* Global variables */
extern int errno;
/* used to pass the current environment to the newly created process instead of the array envp[] */
extern char **environ;
char sectionfinal_to_list[255]; /* string to pass to the child process */
char section_to_list[255]; /* answered by user, part of final string passed to the child process */
/* sections available in Fink at the time of writing */
char *section_name[nb_section] =
{
	"base",
	"crypto",
	"database",
	"devel",
	"editors",
	"games",
	"gnome",
	"graphics",
	"kde",
	"languages",
	"libs",
	"libs/perlmods",
	"net",
	"sci",
	"shells",
	"sound",
	"text",
	"utils",
	"web",
	"x11",
	"x11-system",
	"x11-wm",
};

/* Function to execute while entering the child process */
static void exec_finklistsection_cmd(void)
{
  /* Define the arguments to pass to the function execve */
  static char *argv[] = {"fink", "list", "-t", sectionfinal_to_list, NULL};

  /* Just to trace the execution */
  printf("Entering the exec_finklistsection_cmd\n");

  /* Execute the execve function */
  execve(FINK_PATH, argv, environ);

  /* If the programm goes here, call to execve has failed */
  printf("Call to execve has failed: %s\n", strerror(errno));

  /* Pass the status to parent process */
  exit(EXIT_FAILURE);
}

int main(void)
{
  pid_t child1_pid; /* pid of the child process */
  int i; /* counter for printing the available sections */
  int section_number; /* section number - a convenient way to refer to the section to list */
  int dup1; /* return from dup */
  int pipestatus; /* return from pipe */
  int pip[2]; /* pipes */
  int closestatus; /* return from close */
  

  /* Ask for the section to list */
  for (i = 0; i < nb_section; i++)
  {
	  printf("%d - %s\n", i, section_name[i]);
  }

	printf("Enter the number corresponding to the desired section: ");
	scanf("%d", §ion_number);
	if (section_number < 0 || section_number >= nb_section || isdigit(section_number))
	{
		  exit(EXIT_FAILURE);
	}

	/* Build the string to pass to the child process */
	strcpy(sectionfinal_to_list, "--section=");
	strcat(sectionfinal_to_list, section_name[section_number]);

  /* Create the pipes */
  pipestatus = pipe(pip);
  
  /* Pipe fails */
  if (pipestatus == -1)
  {
      printf("Error while creating the pipe: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
  }
  
  /*Create the child process */
  child1_pid = fork();
  
  if ((int)child1_pid == -1)
    {
      printf("Error in creation of first child process: %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }
  else if (child1_pid == 0)
    {
      printf("The pid of the parent process is: %d\n", (int)getppid());
	  
      /* Close stdout */
      closestatus = close(STDOUT_FILENO);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing stdout: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Redirect pip[1] */
      dup1 = dup(pip[1]);

      /* Dup fails */
      if (dup1 == -1)
	  {
		  printf("Error while redirecting pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[1] */
      closestatus = close(pip[1]);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[0] */
      closestatus = close(pip[0]);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }
	  
      /* Execute the command */
	  exec_finklistsection_cmd();	  
    }
  else
    {
      /* Close stdin */
      closestatus = close(STDIN_FILENO);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing stdin: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Redirect pip[0] */
      dup1 = dup(pip[0]);

      /* Dup fails */
      if (dup1 == -1)
	  {
		  printf("Error while redirecting pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[0] */
      closestatus = close(pip[0]);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing pip[0]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Close pip[1] */
      closestatus = close(pip[1]);

      /* Close fails */
      if (closestatus == -1)
	  {
		  printf("Error while closing pip[1]: %s.\n", strerror(errno));
		  exit(EXIT_FAILURE);
	  }

      /* Exec the command */
      execlp("more", "more", NULL);

      /* Exec fails */
      printf("Error while executing the command sort: %s.\n", strerror(errno));
      exit(EXIT_FAILURE);
	}
	  
  return 0;
}

Third program

Three processes

This is an extension of the first variation to deal with two pipes and three processes.

Steps

Progsys 05-05

In the parent process, a first pipe pip1 is created, then a first child process is forked. When forking, all the descriptors are duplicated. That means there are descriptors for stdin, stdout and pip1 in the first child process as in the parent.

Then, in the first child process, we redirect the write end of pip1 to stdout. We don't need anymore the descriptor for the write end of pip1, so we close it. We close also the read end of pip1, as we you want to duplicate it in the second child process.

Then, in the first child process, a second pipe pip2 is created. Again, when forking a new child process, we obtain descriptors for stdin, stdout, pip2 write and read ends in the second child process.

Then, in the second child process, we redirect the write end of pip2 to stdout. We don't need anymore the descriptor for the write end of pip2, so we close it. We close also the read end of pip2, as we don't need it.

The second child process executes the command ps, then we return in the first child process where we redirect the read end of pip2 to stdin. Then we close the read and write ends of pip2, as we don't need them anymore. The first child process executes the sort command.

Then we return in the parent process, where we redirect the read end of pip1 to stdin. We close the read and write ends of pip1, as we don't need them anymore and the parent process executes the grep command.

Below is a picture which shows the flow of date between parent and child processes.

Progsys 05-06

Primitives used

Dup2: int dup2(int oldd, int newdd)

Similar to dup, except that the new descriptor is named, which avoids possible confusion.

Library to be used: unistd.h

Man page: dup2(2) - system calls.

/* pipeessai2.c

Program to run the command:ps -alxjww | sort -k -9 -k 15 -k 2 -k 3 -k 10 -k 1 | grep -w username

Use pipes and dup2:

pipe:

first pipe between grep and sort
second pipe between sort and ps

dup2:
read end of first pipe -> stdin
write end of first pipe -> stdout / child 1
read end of second pipe -> stdin
write end of second pipe -> stdout / child 1

*/

/* Includes */
#include <stdio.h>        /* for access to the standard i/o files, printf */
#include <unistd.h>       /* for fork, read, close, pipe, dup */
#include <sys/wait.h>     /* for wait */
#include <stdlib.h>       /* for exit, EXIT_SUCCESS, EXIT_FAILURE */
#include <sys/errno.h>    /* for ECHILD*/
#include <sys/types.h>		/* for getuid */

/* Extern global variables */
static char *userName; /* for retrieving user's name */

/* Function declarations: wrapper for primitives to handle errors */
void Pipe(int *fildes);
pid_t Fork(void);
void Close(int fd);
void Dup2(int fd1, int fd2);

int main()
{
	/* Variables */
	int pip1[2], pip2[2];  /* pointers to file descriptors for pipes */
	int pid1, pid2;           /* returned from fork */
	
	/* Create pip1 */
	Pipe(pip1);

	/* First child process */
	if ( (pid1 = (int)Fork()) == 0)
	{
		/* Redirect the write end of pip1 to stdout */
		Dup2(pip1[1], STDOUT_FILENO);
		
		/* Close duplicated descriptors */
		Close(pip1[1]);
		Close(pip1[0]);
		
		/* Create pip2 */
		Pipe(pip2);

		 /* Second Child process */
  		if ((pid2 = (int)Fork()) == 0)
  		{
 		    /* Redirect the write end of pip2 to stdout */
			Dup2(pip2[1], STDOUT_FILENO);
		 	
			/* Close duplicated descriptors */
			Close(pip2[1]);
			Close(pip2[0]);
		    
			/* Execute ps */
			execlp("ps", "ps", "-alxjww", NULL);
			
			/* Execlp fails */
			perror("Error while executing the command ps");
      		exit(EXIT_FAILURE);
    	}
		/* Again first child process */
		else
		{
			/* Redirect the read end of pip2 to stdin */
			Dup2(pip2[0], STDIN_FILENO);
			
			/* Close duplicated descriptors */
			Close(pip2[1]);
			Close(pip2[0]);
     		
			/* Execute sort */
			execlp("sort", "sort", "-k", "9", "-k", "15", "-k", "2", "-k", "3", "-k", "10", "-k", "1", NULL);
			
			/* Execlp fails */
			perror("Error while executing the command sort\n");
			exit(EXIT_FAILURE);
    	}
	}
	/* Parent process */
	else
	{
		/* Redirect the read end of pip1 to stdin */
		Dup2(pip1[0], STDIN_FILENO);
		
		/* Close duplicated descriptors */
		Close(pip1[0]);
		Close(pip1[1]);
		
		/* Retrieve the user name */
		userName = getenv("LOGNAME");
		
		/* Execute grep */
		execlp("grep", "grep", "-w", userName, NULL);
		
		/* Execlp failed */
		perror("Error while executing the command grep\n");
		exit(EXIT_FAILURE);
	}
		
	return 0;
}

void Pipe(int *fildes)
{
	if ( pipe(fildes) < 0 )
	{
		perror("Error while creating the pipe\n");
		exit(EXIT_FAILURE);
	}
}

pid_t Fork()
{
	pid_t pid;

	if ( ( pid = fork() ) == -1 )
	{
		perror("Error while forking\n");
		exit(EXIT_FAILURE);
	}

	return pid;
}
	
void Close(int fd)
{
	if ( close(fd) == -1)
	{
		perror("Error while closing\n");
		exit(EXIT_FAILURE);
	}
}

void Dup2(int fd1, int fd2)
{
	if (dup2(fd1, fd2) == -1)
	{
		perror("Error redirecting read/write ends of pipes to stdin/stdout\n");
		exit(EXIT_FAILURE);
	}
}

Contents - Process scheduling - Fork and Wait - Pthread and Exec - Exec - Pipes - Message queues - Memory management - Paging and segmentation - Synchronization (1) - Synchronization (2) - File System Management - Socket Programming (1) - Revision

Powered by Apache/1.3.41 (Darwin) PHP/4.4.8 on Mac OS X bluefish distributed.net Cssed icon Conglomerate icon Valid HTML 4.0.1 Valid CSS
Local date (dd/mm/yyyy): 08/10/2008 13:24:41 CEST