我在处理管道和子进程时遇到了一些问题。
我需要
预期输出为:
$ ./a.out 1C < card.txt
Child : 1, pid 1593 :
<S2 S3 S9 ><H9 H6 HA H8 ><C6 CK ><D8 DQ D7 D3 >
Child : 2, pid 1594 :
<SA S6 S7 S4 ><H4 HJ H7 ><CQ C9 CT ><DT D2 D9 >
Child : 3, pid 1595 :
<SQ S5 ><H2 ><C7 C5 C8 CA C4 CJ C3 ><DA D5 >
Child : 4, pid 1596 :
<S8 SJ SK ST ><HK HT H5 H3 HQ ><C2 ><D4 D6 >
child 1: H9
parent: child 1 played H9
child 2: CQ
parent: child 2 played CQ
child 3: H2
parent: child 3 played H2
child 4: HK
parent: child 4 played HK
但实际输出如下:
parent: child 1 played (null)parent: child 2 played (null)parent: child 3 played (null)parent: child 4 played (null)
为什么?如何解决问题?
代码创建了此输出:
#include <stdio.h>
#include <string.h>
#define BUFFERSIZE 51
int i=0;
int currpid, s;
char *buf[BUFFERSIZE];
char *array[BUFFERSIZE];
int n;
char *buffer[100];
/** child to parent pipe */
int child_parent[2];
/** parent to child pipe */
int parent_child[2];
/** child2 to parent pipe */
int child2_parent[2];
/** parent to child2 pipe */
int parent_child2[2];
/** child3 to parent pipe */
int child3_parent[2];
/** parent to child3 pipe */
int parent_child3[2];
/** child4 to parent pipe */
int child4_parent[2];
/** parent to child4 pipe */
int parent_child4[2];
void childFunction(){
int j;
for( i = s+1; i < BUFFERSIZE; i += 4 )
{
buf[j] = array[i];
j++;
}
printf("\n<");
int r;
char *e;
for( r = 0; r < j; r++ )
{
int index;
e = strchr(buf[r],'S');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for( r = 0; r < j; r++ )
{
int index;
e = strchr(buf[r],'H');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for( r = 0; r < j; r++ )
{
int index;
e = strchr(buf[r],'C');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for( r = 0; r < j; r++ )
{
int index;
e = strchr(buf[r],'D');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">\n");
switch (s){
case 0:
close(parent_child[1]);
close(parent_child[0]);
close(child_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child_parent[1], &buffer[0], strlen(buffer[0]));
close(child_parent[1]);
break;
case 1:
close(parent_child2[1]);
close(parent_child2[0]);
close(child2_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child2_parent[1], &buffer[0], strlen(buffer[0]));
close(child2_parent[1]);
break;
case 2:
close(parent_child3[1]);
close(parent_child3[0]);
close(child3_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child3_parent[1], &buffer[0], strlen(buffer[0]));
close(child3_parent[1]);
break;
case 3:
close(parent_child4[1]);
close(parent_child4[0]);
close(child4_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child4_parent[1], &buffer[0], strlen(buffer[0]));
close(child4_parent[1]);
break;
}
}
void parentFunction(){
switch (s){
case 0:
close(child_parent[1]);
close(parent_child[1]);
close(parent_child[0]);
read(child_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child_parent[0]);
break;
case 1:
close(child2_parent[1]);
close(parent_child2[1]);
close(parent_child2[0]);
read(child2_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child2_parent[0]);
break;
case 2:
close(child3_parent[1]);
close(parent_child3[1]);
close(parent_child3[0]);
read(child3_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child3_parent[0]);
break;
case 3:
close(child4_parent[1]);
close(parent_child4[1]);
close(parent_child4[0]);
read(child4_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child4_parent[0]);
break;
}
}
int main(int argc, char *argv[])
{
int ch;
ssize_t rread;
char *line = NULL;
size_t len = 0;
while (rread = getdelim( &line, &len, '\0', stdin) != -1) {
}
array[i] = strtok(line," ");
while(array[i]!=NULL)
{
array[++i] = strtok(NULL," ");
}
int childlimit = 4;
int childpids[childlimit];
int currpid;
if (pipe(child_parent) == 0 && pipe(parent_child) == 0 && pipe(child2_parent) == 0 && pipe(parent_child2) == 0 && pipe(child3_parent) == 0 && pipe(parent_child3) == 0 && pipe(child4_parent) == 0 && pipe(parent_child4) == 0)
{
for(s=0; s<childlimit; s++){
switch(currpid = fork()){
case 0:
printf("Child : %d, pid %d : ", s+1, getpid() );
childFunction();
break;
case -1:
printf("Error when forking\n");
return 1;
default:
// in the father
childpids[s] = currpid;
parentFunction();
break;
}
}
//wait for all child created to die
waitpid(-1, NULL, 0);
}
}
答案 0 :(得分:1)
当您开始使用child2_parent
和parent_child2
等名称时,会有一个数组试图逃离您的变量。当你有4组这些变量时,它是可怕的。
代码存在很多问题。这是一个完全重写。错误报告给stderr
。检查大多数系统调用。已读取的数据的诊断打印输出。有一个函数split_string()
可以将字符串拆分为空格中的单词。它在父组件和子组件中都使用。孩子们不再能够访问字符串数据 - 所有全局变量都已消失。
代码仍远未达到最佳状态。在开始孩子之前,没有特别需要打开所有管道;这个过程是同步的。依次为每个孩子创建管道是可行的,甚至是明智的。就目前而言,每个孩子只能关闭四分之一的可用管道描述符。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
enum { MAX_KIDS = 4 };
enum { LIST_SIZE = 1024 };
enum { MAX_WORDS = LIST_SIZE / 3 };
static int split_string(char *data, char *words[], int max_words)
{
int num_words = 0;
char *src = data;
char *token;
while ((token = strtok(src, " \n\t")) != NULL)
{
words[num_words++] = token;
if (num_words >= max_words)
break;
src = NULL;
}
return num_words;
}
static void childFunction(int s, int f_pipe[2], int t_pipe[2])
{
srand(getpid());
close(f_pipe[1]);
close(t_pipe[0]);
char data[LIST_SIZE];
int nbytes;
if ((nbytes = read(f_pipe[0], data, sizeof(data))) <= 0)
{
fprintf(stderr, "child %d (PID %d): failed to read pipe\n", s, (int)getpid());
exit(1);
}
data[nbytes] = '\0';
close(f_pipe[0]);
char *words[MAX_WORDS];
int num_words = split_string(data, words, MAX_WORDS);
char *word = words[rand() % num_words];
int len = strlen(word);
if (write(t_pipe[1], word, len) != len)
{
fprintf(stderr, "child %d (PID %d): failed to write [%s] to pipe\n", s, (int)getpid(), word);
exit(1);
}
close(t_pipe[1]);
exit(0);
}
static void parentFunction(int s, int c_pid, int t_pipe[2], int f_pipe[2], char *words[], int max_words)
{
close(t_pipe[0]);
close(f_pipe[1]);
char buffer[LIST_SIZE];
char *data = buffer;
const char *pad = "";
for (int i = s; i < max_words; i += MAX_KIDS)
{
int n = snprintf(data, (size_t)(buffer + sizeof(buffer) - data), "%s%s", pad, words[i]);
data += n;
pad = " ";
}
printf("Send [%s] to child %d\n", buffer, s);
/* Write list of words to child */
int nbytes = data - buffer;
if (write(t_pipe[1], buffer, nbytes) != nbytes)
{
fprintf(stderr, "parent: failed to write to child %d (PID %d)\n", s, c_pid);
exit(1);
}
close(t_pipe[1]);
/* Read selected word from child */
nbytes = read(f_pipe[0], buffer, sizeof(buffer));
if (nbytes <= 0)
{
fprintf(stderr, "parent: failed to read from child %d (PID %d)\n", s, c_pid);
exit(1);
}
buffer[nbytes] = '\0';
close(f_pipe[0]);
printf("parent: child %d (PID %d) played %s\n", s, c_pid, buffer);
}
int main(void)
{
ssize_t rread;
char *line = NULL;
size_t len = 0;
if ((rread = getdelim(&line, &len, '\0', stdin)) == -1)
{
fprintf(stderr, "Unexpected EOF on standard input\n");
return 1;
}
printf("line [%s]\n", line);
char *wordlist[MAX_WORDS];
int num_words = split_string(line, wordlist, MAX_WORDS);
printf("Word list:");
int i;
for (i = 0; i < num_words; i++)
{
if (i % 10 == 0 && i > 0)
printf("%10s", "");
printf(" %2d [%s]", i, wordlist[i]);
if (i % 10 == 9)
putchar('\n');
}
if (i % 10 != 0)
putchar('\n');
printf("%d words\n", i);
for (int kid = 0; kid < MAX_KIDS; kid++)
{
printf("Words for child %d:", kid);
for (int word = kid; word < i; word += MAX_KIDS)
printf(" [%s]", wordlist[word]);
putchar('\n');
}
int child_parent[MAX_KIDS][2];
int parent_child[MAX_KIDS][2];
for (int i = 0; i < MAX_KIDS; i++)
{
if (pipe(child_parent[i]) != 0 || pipe(parent_child[i]) != 0)
{
fprintf(stderr, "failed to create pipes for child %d\n", i);
exit(1);
}
}
for (int s = 0; s < MAX_KIDS; s++)
{
int currpid = fork();
if (currpid < 0)
{
fprintf(stderr, "Error when forking\n");
exit(1);
}
else if (currpid == 0)
{
printf("Child : %d, pid %d:\n", s, getpid() );
childFunction(s, parent_child[s], child_parent[s]);
}
else
parentFunction(s, currpid, parent_child[s], child_parent[s], wordlist, num_words);
}
int corpse;
int status;
while ((corpse = waitpid(-1, &status, 0)) > 0)
printf("PID %d died with exit status 0x%.4X\n", corpse, status);
}
给定一个数据文件:
S2 SA SQ S8 S3 S6 S5 SJ S9 S7 H2 SK H9 S4 C7
ST H6 H4 C5 HK HA HJ C8 HT H8 H7 CA H5 C6 CQ
C4 H3 CK C9 CJ HQ D8 CT C3 C2 DQ DT DA D4 D7
D2 D5 D6 D3 D9
该程序的一个示例输出是:
line [S2 SA SQ S8 S3 S6 S5 SJ S9 S7 H2 SK H9 S4 C7
ST H6 H4 C5 HK HA HJ C8 HT H8 H7 CA H5 C6 CQ
C4 H3 CK C9 CJ HQ D8 CT C3 C2 DQ DT DA D4 D7
D2 D5 D6 D3 D9
]
Word list: 0 [S2] 1 [SA] 2 [SQ] 3 [S8] 4 [S3] 5 [S6] 6 [S5] 7 [SJ] 8 [S9] 9 [S7]
10 [H2] 11 [SK] 12 [H9] 13 [S4] 14 [C7] 15 [ST] 16 [H6] 17 [H4] 18 [C5] 19 [HK]
20 [HA] 21 [HJ] 22 [C8] 23 [HT] 24 [H8] 25 [H7] 26 [CA] 27 [H5] 28 [C6] 29 [CQ]
30 [C4] 31 [H3] 32 [CK] 33 [C9] 34 [CJ] 35 [HQ] 36 [D8] 37 [CT] 38 [C3] 39 [C2]
40 [DQ] 41 [DT] 42 [DA] 43 [D4] 44 [D7] 45 [D2] 46 [D5] 47 [D6] 48 [D3] 49 [D9]
50 words
Words for child 0: [S2] [S3] [S9] [H9] [H6] [HA] [H8] [C6] [CK] [D8] [DQ] [D7] [D3]
Words for child 1: [SA] [S6] [S7] [S4] [H4] [HJ] [H7] [CQ] [C9] [CT] [DT] [D2] [D9]
Words for child 2: [SQ] [S5] [H2] [C7] [C5] [C8] [CA] [C4] [CJ] [C3] [DA] [D5]
Words for child 3: [S8] [SJ] [SK] [ST] [HK] [HT] [H5] [H3] [HQ] [C2] [D4] [D6]
Send [S2 S3 S9 H9 H6 HA H8 C6 CK D8 DQ D7 D3] to child 0
Child : 0, pid 89366:
parent: child 0 (PID 89366) played HA
Send [SA S6 S7 S4 H4 HJ H7 CQ C9 CT DT D2 D9] to child 1
Child : 1, pid 89367:
parent: child 1 (PID 89367) played S4
Send [SQ S5 H2 C7 C5 C8 CA C4 CJ C3 DA D5] to child 2
Child : 2, pid 89368:
parent: child 2 (PID 89368) played C5
Send [S8 SJ SK ST HK HT H5 H3 HQ C2 D4 D6] to child 3
Child : 3, pid 89369:
parent: child 3 (PID 89369) played D6
PID 89368 died with exit status 0x0000
PID 89367 died with exit status 0x0000
PID 89366 died with exit status 0x0000
PID 89369 died with exit status 0x0000