如何为 n 个子进程实现 n 个管道
how to emplement n pipes for n child processes
我有这段代码,据说可以创建 n 个子节点和 n 个管道(n 作为主参数给出),我想做的是使用方便的管道将 char* 发送到指定的子节点read/write 系统调用但它实际上没有工作(我是系统编程的新手)
这是主要的
int main(int argc, char const *argv[])
{
int tmp,np;
int tube[MAX_PROCESS][2], i;
pid_t pid[MAX_PROCESS];
char *chaine;
if(argc != 2){
perror("Error : nombre d'arguments est invalide\n");
exit(EXIT_FAILURE);
}
tmp = atoi(argv[1]);
if(tmp > 10){
fprintf(stderr,"Erreur : nombre de processus fils doit étre inférieure a %d", MAX_PROCESS);
exit(EXIT_FAILURE);
}
for(i=0;i<tmp;i++){
if(pipe(tube[i]) == -1){
perror("Erreur lors du création du tube");
exit(EXIT_FAILURE);
}
}
printf("fermeture des tubes de lecture dans le pere\n");
for(i=0; i < tmp; i++){
if(close(tube[i][TUBE_LECTURE]) == -1){
fprintf(stderr,"Erreur lors la fermeture de tube de lecture %d\n",i);
exit(EXIT_FAILURE);
}else
printf("tube %d fermé\n", i);
}
printf("lecture a partir du clavier d'une chaine et du numéro du fils voulu : \n");
chaine = (char*) malloc(sizeof(char));
if(scanf("%s %d", chaine, &np) != 2){
perror("Erreur de lecture de la chaine ou du numéro du processus fils\n");
exit(EXIT_FAILURE);
}
printf("création des fils...\n");
for(i=0; i<tmp; i++){
if((pid[i] = fork()) == -1){
perror("Erreur lors du création des fils");
exit(EXIT_FAILURE);
}
}
printf("Initialisation fonction 'fils'\n");
for(i=0;i<tmp;i++) {
if(pid[i] == 0)
fils(np,tmp,tube);
}
printf("ecriture dans le tube\n");
if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
perror("Erreur ecriture dans le tube\n");
exit(EXIT_FAILURE);
}
/*fermeture des tubes d'écriture*/
for(i=0; i< tmp; i++){
if(close(tube[i][TUBE_ECRITURE]) == -1){
perror("Erreur lors la fermeture de tube de l'écriture\n");
exit(EXIT_FAILURE);
}
}
/*attente des fils*/
for(i=0;i<tmp;i++){
if(waitpid(pid[i],NULL, 0) == -1){
fprintf(stderr,"Erreur lors de l'attente du fils %d",i);
exit(EXIT_FAILURE);
}
else
printf("le fils %d a terminé\n", i);
}
printf("tous les fils ont terminé\n");
return EXIT_SUCCESS;
}
它正在打印以下错误:
fermeture des tubes de lecture dans le pere
tube 0 fermé
tube 1 fermé
tube 2 fermé
tube 3 fermé
lecture a partir du clavier d'une chaine et du numéro du fils voulu :
yassine
2
création des fils...
Initialisation fonction 'fils'
ecriture dans le tube
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
你的概念错误很多。
您不能在执行 fork
之前关闭管道的读取端。这
children继承了parents的文件描述符状态,你必须
fork
然后在parent进程
中关闭管道的读取端
当你使用fork
时,你必须为child进程和
parent
进程。你没有这样做,但不是在正确的地方。你做
printf("création des fils...\n");
for(i=0; i<tmp; i++){
if((pid[i] = fork()) == -1){
perror("Erreur lors du création des fils");
exit(EXIT_FAILURE);
}
}
这里你正在创建许多 children,children 并执行
fork
在接下来的迭代中,你最终不会得到几个 children,而是得到一个
child人全军。根据 tmp
的大小,您可能会消耗所有
fork
允许进程。在您的情况下,只有 parent 应该执行 fork
(请参阅下面的代码)。
此代码:
chaine = (char*) malloc(sizeof(char));
if(scanf("%s %d", chaine, &np) != 2){
perror("Erreur de lecture de la chaine ou du numéro du processus fils\n");
exit(EXIT_FAILURE);
}
你 should not cast malloc
在这里你正在为 一个 分配 space
字符,为什么还要费心为单个字符动态分配内存。
然后你使用 in scanf
来读取一个字符串。这会溢出缓冲区,因为
字符串以 '[=26=]'
结尾,即使对于长度为 1 的字符串,您也需要 2
spaces.
我不太明白np
是什么意思,后来你明白了
if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
但你从不检查 np
是否在 [0-MAX_PROCESS
] 范围内,你可能会访问
管道数组越界。
这里
if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
sizeof(chaine)
给出了指针的大小,但是如果试图发送一个字符串,
你应该写 strlen(chaine)+1
字节,+1
用于 [=33=]
-终止
byte 否则管道另一端的 child 不知道有多少
它应该为字符串读取的字节数。
perror
只应在函数 returns 错误值并设置时使用
errno
。代码开头,如果argc != 2
,那么这个不设置
errno
为任何值,使用 perror
将打印出误导性的错误消息。你
应该使用 fprintf(stderr, "...
代替。
所以这是一个版本(没有fils
功能,因为我不知道它是什么
确实)向您展示了如何 fork
并通过管道发送数据。
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#define MAX_PROCESS 5
int child_process(int id, int tube[2], int np)
{
int ret = 0;
char buffer[100] = {0};
printf(" Child %d, attempt to read 100 characters from parent. np is: %d\n", id, np);
// closing writing end
close(tube[1]);
ssize_t size = read(tube[0], buffer, sizeof buffer);
if(size <= 0)
{
printf(" Child %d, could not read from parent\n", id);
ret = 1;
} else {
// making sure to [=14=]-terminate string
if(buffer[size] != 0)
buffer[size - ( size == sizeof(buffer) ? 1 : 0)] = 0;
printf(" Child %d: parent sent '%s'\n", id, buffer);
}
// closing reading end
close(tube[0]);
return ret;
}
int main(int argc, char **argv)
{
int tube[MAX_PROCESS][2], i;
pid_t pid[MAX_PROCESS];
if(argc != 2){
fprintf(stderr, "Error : nombre d'arguments est invalide\n");
exit(EXIT_FAILURE);
}
int noc = atoi(argv[1]);
if(noc <= 0 || noc > MAX_PROCESS)
{
fprintf(stderr, "Erreur : nombre de processus fils doit étre inférieure a %d", MAX_PROCESS);
exit(EXIT_FAILURE);
}
printf("lecture a partir du clavier d'une chaine et du numéro du fils voulu : \n");
char chaine[100];
int np;
if(scanf("%99s %d", chaine, &np) != 2)
{
fprintf(stderr, "Erreur de lecture de la chaine ou du numéro du processus fils\n");
exit(EXIT_FAILURE);
}
if(np < 0 || np >= MAX_PROCESS)
{
fprintf(stderr, "Error: np must be in range [0 - %d]\n", MAX_PROCESS-1);
exit(EXIT_FAILURE);
}
printf("création des fils...\n");
for(i = 0; i < noc; ++i)
{
if(pipe(tube[i]) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
pid[i] = fork();
if(pid[i] == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
if(pid[i] == 0)
{
// CHILD PROC
exit(child_process(i, tube[i], np));
}
// PARENT PROC
// closing reading end
close(tube[i][0]);
}
// parent sends data to children
for(i = 0; i < noc; ++i)
{
size_t len = strlen(chaine) + 1;
if(write(tube[i][1], chaine, len) != len)
fprintf(stderr, "Parent could not send the whole string to the child %d\n", i);
// closing writing pipe
close(tube[i][1]);
}
for(i = 0; i < noc; ++i)
{
if(waitpid(pid[i],NULL, 0) == -1){
fprintf(stderr,"Erreur lors de l'attente du fils %d\n",i);
exit(EXIT_FAILURE);
}
else
printf("le fils %d a terminé\n", i);
}
exit(EXIT_SUCCESS);
}
有这样的输出:
$ ./a 5
lecture a partir du clavier d'une chaine et du numéro du fils voulu :
HelloWorld 3
création des fils...
Child 0, attempt to read 100 characters from parent. np is: 3
Child 1, attempt to read 100 characters from parent. np is: 3
Child 2, attempt to read 100 characters from parent. np is: 3
Child 0: parent sent 'HelloWorld'
Child 2: parent sent 'HelloWorld'
Child 3, attempt to read 100 characters from parent. np is: 3
Child 1: parent sent 'HelloWorld'
Child 3: parent sent 'HelloWorld'
Child 4, attempt to read 100 characters from parent. np is: 3
Child 4: parent sent 'HelloWorld'
le fils 0 a terminé
le fils 1 a terminé
le fils 2 a terminé
le fils 3 a terminé
le fils 4 a terminé
我有这段代码,据说可以创建 n 个子节点和 n 个管道(n 作为主参数给出),我想做的是使用方便的管道将 char* 发送到指定的子节点read/write 系统调用但它实际上没有工作(我是系统编程的新手)
这是主要的
int main(int argc, char const *argv[])
{
int tmp,np;
int tube[MAX_PROCESS][2], i;
pid_t pid[MAX_PROCESS];
char *chaine;
if(argc != 2){
perror("Error : nombre d'arguments est invalide\n");
exit(EXIT_FAILURE);
}
tmp = atoi(argv[1]);
if(tmp > 10){
fprintf(stderr,"Erreur : nombre de processus fils doit étre inférieure a %d", MAX_PROCESS);
exit(EXIT_FAILURE);
}
for(i=0;i<tmp;i++){
if(pipe(tube[i]) == -1){
perror("Erreur lors du création du tube");
exit(EXIT_FAILURE);
}
}
printf("fermeture des tubes de lecture dans le pere\n");
for(i=0; i < tmp; i++){
if(close(tube[i][TUBE_LECTURE]) == -1){
fprintf(stderr,"Erreur lors la fermeture de tube de lecture %d\n",i);
exit(EXIT_FAILURE);
}else
printf("tube %d fermé\n", i);
}
printf("lecture a partir du clavier d'une chaine et du numéro du fils voulu : \n");
chaine = (char*) malloc(sizeof(char));
if(scanf("%s %d", chaine, &np) != 2){
perror("Erreur de lecture de la chaine ou du numéro du processus fils\n");
exit(EXIT_FAILURE);
}
printf("création des fils...\n");
for(i=0; i<tmp; i++){
if((pid[i] = fork()) == -1){
perror("Erreur lors du création des fils");
exit(EXIT_FAILURE);
}
}
printf("Initialisation fonction 'fils'\n");
for(i=0;i<tmp;i++) {
if(pid[i] == 0)
fils(np,tmp,tube);
}
printf("ecriture dans le tube\n");
if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
perror("Erreur ecriture dans le tube\n");
exit(EXIT_FAILURE);
}
/*fermeture des tubes d'écriture*/
for(i=0; i< tmp; i++){
if(close(tube[i][TUBE_ECRITURE]) == -1){
perror("Erreur lors la fermeture de tube de l'écriture\n");
exit(EXIT_FAILURE);
}
}
/*attente des fils*/
for(i=0;i<tmp;i++){
if(waitpid(pid[i],NULL, 0) == -1){
fprintf(stderr,"Erreur lors de l'attente du fils %d",i);
exit(EXIT_FAILURE);
}
else
printf("le fils %d a terminé\n", i);
}
printf("tous les fils ont terminé\n");
return EXIT_SUCCESS;
}
它正在打印以下错误:
fermeture des tubes de lecture dans le pere
tube 0 fermé
tube 1 fermé
tube 2 fermé
tube 3 fermé
lecture a partir du clavier d'une chaine et du numéro du fils voulu :
yassine
2
création des fils...
Initialisation fonction 'fils'
ecriture dans le tube
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Initialisation fonction 'fils'
Erreur lors de la lecture Bad file descriptor
Erreur lors de la lecture Bad file descriptor
你的概念错误很多。
您不能在执行
fork
之前关闭管道的读取端。这 children继承了parents的文件描述符状态,你必须fork
然后在parent进程 中关闭管道的读取端
当你使用
fork
时,你必须为child进程和parent
进程。你没有这样做,但不是在正确的地方。你做printf("création des fils...\n"); for(i=0; i<tmp; i++){ if((pid[i] = fork()) == -1){ perror("Erreur lors du création des fils"); exit(EXIT_FAILURE); } }
这里你正在创建许多 children,children 并执行
fork
在接下来的迭代中,你最终不会得到几个 children,而是得到一个 child人全军。根据tmp
的大小,您可能会消耗所有fork
允许进程。在您的情况下,只有 parent 应该执行fork
(请参阅下面的代码)。此代码:
chaine = (char*) malloc(sizeof(char)); if(scanf("%s %d", chaine, &np) != 2){ perror("Erreur de lecture de la chaine ou du numéro du processus fils\n"); exit(EXIT_FAILURE); }
你 should not cast
malloc
在这里你正在为 一个 分配 space 字符,为什么还要费心为单个字符动态分配内存。 然后你使用 inscanf
来读取一个字符串。这会溢出缓冲区,因为 字符串以'[=26=]'
结尾,即使对于长度为 1 的字符串,您也需要 2 spaces.我不太明白
np
是什么意思,后来你明白了if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
但你从不检查
np
是否在 [0-MAX_PROCESS
] 范围内,你可能会访问 管道数组越界。这里
if(write(tube[np][TUBE_ECRITURE],chaine,sizeof(chaine)) == -1){
sizeof(chaine)
给出了指针的大小,但是如果试图发送一个字符串, 你应该写strlen(chaine)+1
字节,+1
用于[=33=]
-终止 byte 否则管道另一端的 child 不知道有多少 它应该为字符串读取的字节数。perror
只应在函数 returns 错误值并设置时使用errno
。代码开头,如果argc != 2
,那么这个不设置errno
为任何值,使用perror
将打印出误导性的错误消息。你 应该使用fprintf(stderr, "...
代替。
所以这是一个版本(没有fils
功能,因为我不知道它是什么
确实)向您展示了如何 fork
并通过管道发送数据。
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#define MAX_PROCESS 5
int child_process(int id, int tube[2], int np)
{
int ret = 0;
char buffer[100] = {0};
printf(" Child %d, attempt to read 100 characters from parent. np is: %d\n", id, np);
// closing writing end
close(tube[1]);
ssize_t size = read(tube[0], buffer, sizeof buffer);
if(size <= 0)
{
printf(" Child %d, could not read from parent\n", id);
ret = 1;
} else {
// making sure to [=14=]-terminate string
if(buffer[size] != 0)
buffer[size - ( size == sizeof(buffer) ? 1 : 0)] = 0;
printf(" Child %d: parent sent '%s'\n", id, buffer);
}
// closing reading end
close(tube[0]);
return ret;
}
int main(int argc, char **argv)
{
int tube[MAX_PROCESS][2], i;
pid_t pid[MAX_PROCESS];
if(argc != 2){
fprintf(stderr, "Error : nombre d'arguments est invalide\n");
exit(EXIT_FAILURE);
}
int noc = atoi(argv[1]);
if(noc <= 0 || noc > MAX_PROCESS)
{
fprintf(stderr, "Erreur : nombre de processus fils doit étre inférieure a %d", MAX_PROCESS);
exit(EXIT_FAILURE);
}
printf("lecture a partir du clavier d'une chaine et du numéro du fils voulu : \n");
char chaine[100];
int np;
if(scanf("%99s %d", chaine, &np) != 2)
{
fprintf(stderr, "Erreur de lecture de la chaine ou du numéro du processus fils\n");
exit(EXIT_FAILURE);
}
if(np < 0 || np >= MAX_PROCESS)
{
fprintf(stderr, "Error: np must be in range [0 - %d]\n", MAX_PROCESS-1);
exit(EXIT_FAILURE);
}
printf("création des fils...\n");
for(i = 0; i < noc; ++i)
{
if(pipe(tube[i]) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
pid[i] = fork();
if(pid[i] == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
if(pid[i] == 0)
{
// CHILD PROC
exit(child_process(i, tube[i], np));
}
// PARENT PROC
// closing reading end
close(tube[i][0]);
}
// parent sends data to children
for(i = 0; i < noc; ++i)
{
size_t len = strlen(chaine) + 1;
if(write(tube[i][1], chaine, len) != len)
fprintf(stderr, "Parent could not send the whole string to the child %d\n", i);
// closing writing pipe
close(tube[i][1]);
}
for(i = 0; i < noc; ++i)
{
if(waitpid(pid[i],NULL, 0) == -1){
fprintf(stderr,"Erreur lors de l'attente du fils %d\n",i);
exit(EXIT_FAILURE);
}
else
printf("le fils %d a terminé\n", i);
}
exit(EXIT_SUCCESS);
}
有这样的输出:
$ ./a 5
lecture a partir du clavier d'une chaine et du numéro du fils voulu :
HelloWorld 3
création des fils...
Child 0, attempt to read 100 characters from parent. np is: 3
Child 1, attempt to read 100 characters from parent. np is: 3
Child 2, attempt to read 100 characters from parent. np is: 3
Child 0: parent sent 'HelloWorld'
Child 2: parent sent 'HelloWorld'
Child 3, attempt to read 100 characters from parent. np is: 3
Child 1: parent sent 'HelloWorld'
Child 3: parent sent 'HelloWorld'
Child 4, attempt to read 100 characters from parent. np is: 3
Child 4: parent sent 'HelloWorld'
le fils 0 a terminé
le fils 1 a terminé
le fils 2 a terminé
le fils 3 a terminé
le fils 4 a terminé