LINUX.ORG.RU

История изменений

Исправление vodz, (текущая версия) :

Таки и пришлось за вас всё писать:

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

/* Обработчик сигнала SIGCHLD */
static int *childs;
static int n;

static void
my_handler (int nsig)
{
  int i;

  for(;;) {
	int pid = waitpid (-1, NULL, nsig == 0 ? 0 : WNOHANG);
        if(pid < 0) {
                if(errno == EINTR)
                        continue;
                pid = 0;
        }
	if(pid == 0)
		return;
	for(i = 0; i < n; i++)
		if(childs[i] == pid) {
			childs[i] = 0;
                       if(nsig)
                                return;
		}
  }
}

static int get_int(const char *prompt)
{
	long r;
	char *e;
	char inbuf[128];

	for(;;) {
		printf ("%s ", prompt);
		if(fgets (inbuf, sizeof (inbuf), stdin) == NULL)
			exit(0);
		errno = 0;
		r = strtol(inbuf, &e, 10);
		if(e == inbuf || errno != 0 || *e != '\n' || r <= 0 || r > INT_MAX) {
			fprintf(stderr, "Strange number '%s'\n", inbuf);
		} else {
			return r;
		}
	}
}

#define MSG_LENGHT 60
static void fill_msg(char *buf)
{
	int i;

	for(i = 0; i < MSG_LENGHT; i++) {
		buf[i] = '!' + (rand() % ('~' - ' '));
	}
	buf[i] = '\n';
}

int
main (void)
{
  int fd, i, m;
  pid_t pid;
  ssize_t r;
  char *file_name;
  int *p_pipefd;
  int *PIP1;
  char inbuf[MSG_LENGHT + 2];

  n = get_int ("Сколько дочерних процессов создать");
  m = get_int ("Количество циклов * количество процессов");

  p_pipefd = malloc (n * 3 * sizeof (int));
  childs = p_pipefd + n * 2;
  for (i = 0; i < n; i++) {
	PIP1 = p_pipefd + i * 2;
	pipe (PIP1);

	fd = snprintf (NULL, 0, "Foo_%d.txt", i + 1);
	file_name = alloca (fd + 1);
	snprintf (file_name, fd + 1, "Foo_%d.txt", i + 1);

	(void) signal (SIGCHLD, my_handler);

	if ((pid = fork ()) != 0) {
	  //PARENT
	  if(pid < 0) {
		fprintf(stderr, "fork(): %s\n", strerror(errno));
		return 1;
	  }
	  close (PIP1[0]);
	  childs[i] = pid;

	} else {
	  //CHILD
	  int my_pid = getpid();

	  close (PIP1[1]);
	  fd = open (file_name, O_WRONLY | O_CREAT, 0666);
	  if (fd == -1) {
		fprintf (stderr, "File '%s' create failed!\n", file_name);
		return 1;
	  }

	  while ((r = read (PIP1[0], inbuf, MSG_LENGHT + 1)) > 0) {
		write (fd, inbuf, r);
		printf ("I (%d) receive: %s", my_pid, inbuf);
	  }
	  printf ("I (%d) exited\n", my_pid);
	  return 0;
	}
  }

  for (i = 0; i < (n * m); i++) {
	fd = rand () % n;
	fill_msg(inbuf);
	printf("Parent send to %d pid\n", childs[fd]);
	write (p_pipefd[fd * 2 + 1], inbuf, MSG_LENGHT + 1);
  }
  for (i = 0; i < n; i++)
	close (p_pipefd[i * 2 + 1]);

  my_handler(0);
  return 0;
}
$ ./a.out
Сколько дочерних процессов создать 3
Количество циклов * количество процессов 4
Parent send to 6624 pid
Parent send to 6623 pid
Parent send to 6623 pid
Parent send to 6624 pid
Parent send to 6624 pid
Parent send to 6624 pid
I (6623) receive: A07$Q:vFEr_`!f%w>/$U+%59T`7z+kwe6/%gczHCm)>**C<aQY8uwf0LaFa(
Parent send to 6623 pid
Parent send to 6624 pid
Parent send to 6623 pid
I (6623) receive: Zlb$,d"BGDJibmr@+op}("vm1CPq&qXyxU8&::G{wpeZyY5%c@#jB4rRW]^v
Parent send to 6623 pid
Parent send to 6623 pid
I (6623) receive: MWdS1tD2O)^mgLY2<^DUnz+;B)_3o=4=/3,?)OkqWJyZvT'M3d=#`GW#j85Z
Parent send to 6625 pid
I (6623) receive: 8>cj7;sb4?SjWIJ(Lb$on!pN-Acg>}Kp=/umcikw)Y|y=H#hE@rN@}7gZyiw
I (6623) receive: O$jwxr[|xmAS';oNWs.v"vR!.TZ)>lVlpAd%NZ=HI]zO3&8jx_{zVh6d=+(t
I (6623) receive: ]{#9zB"V^I:V^$h~Umw5j.km]j,gq;yi8{=3X>$7#=lzZpy0^._IUeR4P]6\
I (6624) receive: %b82j1Sll+2MlR57e3Erubv5Qo2dV<u[9H($Yto`~<.'*]=*o|{"_s6K}GJT
I (6624) receive: 8,IlCNB\0>o;$J5v_SZ~p_[%SIuK((zY3^aVG$MV[=,x#[p{Ie6T`qYN;ix\
I (6625) receive: 0`JG8]~ozQq9Xm.I#>)0|ke|>xM6/DIY%.!V&:F"jS:D[G(]~Jm77S4nfz@0
I (6624) receive: /7?lwt46]%pyKi7't3iuc?VU3?+{8f)G8HN0Wb_5"P0LU`ldsWZW1KGCiQ?=
I (6625) exited
I (6624) receive: b}j+L5aI0vKyA2O":O0,D"<oH^s48K"yI'?1U"Yd3?_SQInjw:u=;LG}+UL\
I (6624) receive: b2|u=<9'B+xl%S}rsKAXg]9I5V4L&m;h!8xWnL^1VW8tE6h9zD,b"E-66Z|;
I (6624) exited
I (6623) exited
Случайное завершение процессов напишите сами.

Исходная версия vodz, :

Таки и пришлось за вас всё писать:

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

/* Обработчик сигнала SIGCHLD */
static int *childs;
static int n;

static void
my_handler (int nsig)
{
  int i;

  for(;;) {
	int pid = waitpid (-1, NULL, nsig == 0 ? 0 : WNOHANG);
	if(pid < 0)
		continue;
	if(pid == 0)
		return;
	for(i = 0; i < n; i++)
		if(childs[i] == pid) {
			childs[i] = 0;
			return;
		}
  }
}

static int get_int(const char *prompt)
{
	long r;
	char *e;
	char inbuf[128];

	for(;;) {
		printf ("%s ", prompt);
		if(fgets (inbuf, sizeof (inbuf), stdin) == NULL)
			exit(0);
		errno = 0;
		r = strtol(inbuf, &e, 10);
		if(e == inbuf || errno != 0 || *e != '\n' || r <= 0 || r > INT_MAX) {
			fprintf(stderr, "Strange number '%s'\n", inbuf);
		} else {
			return r;
		}
	}
}

#define MSG_LENGHT 60
static void fill_msg(char *buf)
{
	int i;

	for(i = 0; i < MSG_LENGHT; i++) {
		buf[i] = '!' + (rand() % ('~' - ' '));
	}
	buf[i] = '\n';
}

int
main (void)
{
  int fd, i, m;
  pid_t pid;
  ssize_t r;
  char *file_name;
  int *p_pipefd;
  int *PIP1;
  char inbuf[MSG_LENGHT + 2];

  n = get_int ("Сколько дочерних процессов создать");
  m = get_int ("Количество циклов * количество процессов");

  p_pipefd = malloc (n * 3 * sizeof (int));
  childs = p_pipefd + n * 2;
  for (i = 0; i < n; i++) {
	PIP1 = p_pipefd + i * 2;
	pipe (PIP1);

	fd = snprintf (NULL, 0, "Foo_%d.txt", i + 1);
	file_name = alloca (fd + 1);
	snprintf (file_name, fd + 1, "Foo_%d.txt", i + 1);

	(void) signal (SIGCHLD, my_handler);

	if ((pid = fork ()) != 0) {
	  //PARENT
	  if(pid < 0) {
		fprintf(stderr, "fork(): %s\n", strerror(errno));
		return 1;
	  }
	  close (PIP1[0]);
	  childs[i] = pid;

	} else {
	  //CHILD
	  int my_pid = getpid();

	  close (PIP1[1]);
	  fd = open (file_name, O_WRONLY | O_CREAT, 0666);
	  if (fd == -1) {
		fprintf (stderr, "File '%s' create failed!\n", file_name);
		return 1;
	  }

	  while ((r = read (PIP1[0], inbuf, MSG_LENGHT + 1)) > 0) {
		write (fd, inbuf, r);
		printf ("I (%d) receive: %s", my_pid, inbuf);
	  }
	  printf ("I (%d) exited\n", my_pid);
	  return 0;
	}
  }

  for (i = 0; i < (n * m); i++) {
	fd = rand () % n;
	fill_msg(inbuf);
	printf("Parent send to %d pid\n", childs[fd]);
	write (p_pipefd[fd * 2 + 1], inbuf, MSG_LENGHT + 1);
  }
  for (i = 0; i < n; i++)
	close (p_pipefd[i * 2 + 1]);

  my_handler(0);
  return 0;
}
$ ./a.out
Сколько дочерних процессов создать 3
Количество циклов * количество процессов 4
Parent send to 6624 pid
Parent send to 6623 pid
Parent send to 6623 pid
Parent send to 6624 pid
Parent send to 6624 pid
Parent send to 6624 pid
I (6623) receive: A07$Q:vFEr_`!f%w>/$U+%59T`7z+kwe6/%gczHCm)>**C<aQY8uwf0LaFa(
Parent send to 6623 pid
Parent send to 6624 pid
Parent send to 6623 pid
I (6623) receive: Zlb$,d"BGDJibmr@+op}("vm1CPq&qXyxU8&::G{wpeZyY5%c@#jB4rRW]^v
Parent send to 6623 pid
Parent send to 6623 pid
I (6623) receive: MWdS1tD2O)^mgLY2<^DUnz+;B)_3o=4=/3,?)OkqWJyZvT'M3d=#`GW#j85Z
Parent send to 6625 pid
I (6623) receive: 8>cj7;sb4?SjWIJ(Lb$on!pN-Acg>}Kp=/umcikw)Y|y=H#hE@rN@}7gZyiw
I (6623) receive: O$jwxr[|xmAS';oNWs.v"vR!.TZ)>lVlpAd%NZ=HI]zO3&8jx_{zVh6d=+(t
I (6623) receive: ]{#9zB"V^I:V^$h~Umw5j.km]j,gq;yi8{=3X>$7#=lzZpy0^._IUeR4P]6\
I (6624) receive: %b82j1Sll+2MlR57e3Erubv5Qo2dV<u[9H($Yto`~<.'*]=*o|{"_s6K}GJT
I (6624) receive: 8,IlCNB\0>o;$J5v_SZ~p_[%SIuK((zY3^aVG$MV[=,x#[p{Ie6T`qYN;ix\
I (6625) receive: 0`JG8]~ozQq9Xm.I#>)0|ke|>xM6/DIY%.!V&:F"jS:D[G(]~Jm77S4nfz@0
I (6624) receive: /7?lwt46]%pyKi7't3iuc?VU3?+{8f)G8HN0Wb_5"P0LU`ldsWZW1KGCiQ?=
I (6625) exited
I (6624) receive: b}j+L5aI0vKyA2O":O0,D"<oH^s48K"yI'?1U"Yd3?_SQInjw:u=;LG}+UL\
I (6624) receive: b2|u=<9'B+xl%S}rsKAXg]9I5V4L&m;h!8xWnL^1VW8tE6h9zD,b"E-66Z|;
I (6624) exited
I (6623) exited
Случайное завершение процессов напишите сами.