gpt4 book ai didi

c - 关于 C 中的 fork() 和 pipe() 等系统调用的问题

转载 作者:太空狗 更新时间:2023-10-29 15:40:48 24 4
gpt4 key购买 nike

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

int main(int argc, char **argv){
int n = atoi(argv[1]);
int superdaddy = getpid();
int p[n+1][2];
int i=0;
int cpid,output;
int result = 0;

if(pipe(p[0])<0){
perror("1");
return 1;
}
if(pipe(p[n])<0){
perror("2");
return 1;
}
output = p[0][1];
if(getpid()==superdaddy){
if(write(p[0][1],&result,sizeof(result))<0){
perror("3");
return 1;
}
if(close(p[0][1])<0){
perror("4");
return 1;
}
}
while(1){
if(i==n){
if(read(p[n-1][0],&result,sizeof(result)<0)){
perror("5");
return 1;
}
result++;
output = p[n][1];
if(write(output,&result,sizeof(result))<0){
perror("6");
return 1;
}
if(close(p[n-1][0])<0){
perror("7");
return 1;
}
if(close(p[n][1])<0){
perror("8");
return 1;
}
break;
}
i++;
cpid = fork();
if(cpid==0){
if(i==n)
continue;
if(pipe(p[i])<0){
perror("9");
return 1;
}
if(read(p[i-1][0],&result,sizeof(result))<0){
perror("10");
return 1;
}
result++;
output = p[i][1];
if(write(output,&result,sizeof(result))<0){
perror("11");
return 1;
}
if(close(p[i-1][0])<0){
perror("12");
return 1;
}

if(close(p[i][1]<0)){
perror("13");
return 1;
}
continue;
}
else if(cpid<0){
perror("14");
return 1;
}
break;
}

if(getpid()==superdaddy){
wait(NULL);
if(read(p[n][0],&result,sizeof(result))<0){
perror("15");
return 1;
}
printf("Result: %d\n",result);
if(close(p[n][0])<0){
perror("16");
return 1;
}
}
return 0;
}

该程序旨在从命令行读取数字 n,然后 fork n 个子进程并创建 n 个管道。进程 p0 将是进程 p1 的父进程,p1 将是 p2 的父进程,依此类推。一个变量(这里命名为result)会通过管道传递,每传递一次就会加1。所以输出也应该是n。管道 Fi 连接 PiP(i+1)。附件是我的代码。

n=1n=2时,程序都能正确输出,对应的是1和2。但是,当 n=3 时,它在错误 5 处给我一个错误的文件错误。我手动跟踪了整个下午的代码,但不知道它有什么问题。有人可以帮忙吗?先欣赏一下!

最佳答案

when n=3, it gives me a bad file error at error 5.

这可以通过删除 if(close(p[i][1]<0)){ 来解决。在你的代码中,因为你需要读取 p[i][0]在你的最后一次迭代中,即

if (i == n) {
if(read(p[n-1][0],&result,sizeof(result)<0)){
...
}
}

这是您的想法的实现,希望对您有所帮助:

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

int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s N\n", argv[0]);
exit(EXIT_FAILURE);
}

int n = atoi(argv[1]);
int pipes[n][2];
int i, val;
pid_t pid;

val = 0;

for (i = 0; i < n; i++) {
if (pipe(pipes[i]) < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
close(pipes[i][1]);
if (read(pipes[i][0], &val, sizeof(val)) != sizeof(val)) {
perror("read");
exit(EXIT_FAILURE);
}

printf("C %d read %d\n", getpid(), val);

val++;
}
else {
close(pipes[i][0]);

printf("P %d writes %d\n", getpid(), val);

if (write(pipes[i][1], &val, sizeof(val)) != sizeof(val)) {
perror("write");
exit(EXIT_FAILURE);
}

if (waitpid(pid, NULL, 0) != pid) {
perror("waitpid");
exit(EXIT_FAILURE);
}
printf("%d is going to leave.\n", getpid());
exit(EXIT_SUCCESS);
}
}

printf("%d is going to leave.\n", getpid());
exit(EXIT_SUCCESS);
}

测试运行:

$ ./a.out 3
P 2005 writes 0
C 2006 read 0
P 2006 writes 1
C 2007 read 1
P 2007 writes 2
C 2008 read 2
2008 is going to leave.
2007 is going to leave.
2006 is going to leave.
2005 is going to leave.

解释:

该代码的框架是for (i = 0; i < n; i++) { pipe(); fork(); } ,这意味着它将创建 n管道,和 n新流程。在每次迭代中,父级将写入 pipes[i][1] child 将从 pipes[i][0] 中阅读.最终,它会创建一个由一系列管道连接起来的流程链,一个值通过这一系列管道从第一个流程传递到最后一个流程。

关于c - 关于 C 中的 fork() 和 pipe() 等系统调用的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22526537/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com