gpt4 book ai didi

c - 我的代码应该将子输出发送给父级。两个进程 exec()。它只是卡住

转载 作者:太空宇宙 更新时间:2023-11-04 08:01:28 24 4
gpt4 key购买 nike

(请看下面我的最终代码;访问教授后的工作版本)

程序设置了一个子到父管道;子级继续执行“exec”以执行“预”过程,其输出连接到连接到父级的管道,父级继续执行“exec”以执行“排序”过程。

到目前为止的变化:代码仍然卡住。我更改了 exec() 调用并进行了其他更改。

不确定问题出在哪里。

第一次修订

/*
Student: Douglas Adolph
Course: Operating Systems
Project #: 1: Part2_childToParent.c

*/

/* The second example of pipe, between a parent and a child*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>

#define MSGSIZE 512

int main()
{
char inbuf[MSGSIZE];
int p[2];
pid_t pid;

if (pipe(p) == -1)
{
perror("pipe call"); // from example code pipe2.c
exit(1);
}

switch(pid = fork()) {
case -1:
perror("fork call"); // from example code pipe2.c
exit(2);
case 0: // child writes to pipe
dup2(p[1], STDOUT_FILENO); // redirect standard output and error output
close(p[0]); // close link
close(p[1]);
execlp("./pre", "pre",(char *)0); // call execl() to execute pre.c
perror("execl() failed!");
return(EXIT_FAILURE);
default: // parent reads from pipe
close(p[1]);
dup2(p[0], STDIN_FILENO); // redirect standard input and error input
execlp("./sort", "sort",(char *)0); // call execl() to execute sort.c
return(EXIT_FAILURE);
}


return(EXIT_FAILURE);
}

下一次修订

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define MSGSIZE 512

int main()
{
char inbuf[MSGSIZE];
int p[2];
pid_t pid;

if (pipe(p) == -1)
{
perror("pipe call"); // from example code pipe2.c
exit(1);
}

switch(pid = fork()) {
case -1:
perror("fork call"); // from example code pipe2.c
exit(2);
case 0: // child writes to pipe
dup(p[1]); // redirect standard output and error output
close(p[0]); // close link
//close(p[1]);
execl("./pre", "pre",(char *)0); // call execl() to execute pre.c
perror("execl() failed!");
return(EXIT_FAILURE);
default: // parent reads from pipe
wait((int *)0);
close(p[1]);
if ((n = read(p[0], inbuf, MSGSIZE)) >= 0) {
printf("in buff");
inbuf[n] = 0; // terminate the string
printf("%s\n", inbuf); // print message
}
execl("./sortC", "sortC",(char *)0); // call execl() to execute sort.c
return(EXIT_FAILURE);
}

return(EXIT_FAILURE);
}

拜访教授,确认需求,成功运行代码后的最终代码:

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

#define MSGSIZE 512

int main() {
char inbuf[MSGSIZE];
int p[2];
pid_t pid;

if (pipe(p) == -1) {
perror("pipe call"); // from example code pipe2.c
exit(1);
}

switch(pid = fork()) {
case -1:
perror("fork call"); // from example code pipe2.c
exit(2);
case 0: // child writes to pipe
close(1);
dup(p[1]); // redirect standard output and error output
close(p[0]);
close(p[1]);
execl("./pre", "pre",(char *)0); // call execl() to execute pre.c
perror("execl() failed!");
return(EXIT_FAILURE);
default: // parent reads from pipe
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execl("./sort", "sort", (char *)0); // call execl() to execute sort.c
return(EXIT_FAILURE);
}

return(EXIT_FAILURE);
}

最佳答案

第一轮

这是您的更新代码的轻微修改版本 — 在问题中标记为“第一次修订”。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MSGSIZE 512

int main(void)
{
//char inbuf[MSGSIZE];
int p[2];

if (pipe(p) == -1)
{
perror("pipe call"); // from example code pipe2.c
exit(1);
}

switch (fork())
{
case -1:
perror("fork call"); // from example code pipe2.c
exit(2);
case 0: // child writes to pipe
dup2(p[1], STDOUT_FILENO); // redirect standard output and error output
close(p[0]); // close link
close(p[1]);
execl("./preC", "preC", (char *)0); // call execl() to execute pre.c
perror("execl() failed!");
return(EXIT_FAILURE);
default: // parent reads from pipe
close(p[1]);
dup2(p[0], STDIN_FILENO);
close(p[0]);
// read(p[0], inbuf, MSGSIZE); // read message in pipe (sent from child)
// printf("%s\n", inbuf); // print message
execl("./sortC", "sortC", (char *)0); // call execl() to execute sort.c
return(EXIT_FAILURE);
}
/*NOTREACHED*/

return(EXIT_FAILURE);
}

主要变化是:

  1. 在调用 dup2() 后关闭管道的第二端。
  2. 修改父分支中的代码以重新处理 I/O 重定向。

在我首选的严格编译选项下编译时没有警告(在仍然运行 macOS Sierra 10.12.6 的 Mac 上,使用 GCC 7.2.0):

gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
fork79.c -o fork79

我创建了一对最小的 shell 脚本来作为 preCsortC:

$ cat preC
#!/bin/sh
exec ls -t *.c
$ cat sortC
#!/bin/sh
exec sort
$

preC 的基本输出是:

fork79.c        pth47.c         cpp13.c         th89.c          mnmx67.c
pl53.c pth23.c fd19.c cp53.c mm19.c
da73.c bs79.c fd53.c th59.c mm53.c
example.c pm73.c fd23.c th19.c mm23.c
rf13.c nr13.c fd97.c cp41.c mm59.c
pipe97.c cola83.c fd47.c mnmx71.c bst29.c
pipe83.c cola61.c cp79.c mergesort47.c

(通过管道输出时,每行列出一个文件名。)

运行 fork97 的输出(如图所示,通过编译 fork79.c 创建)是:

bs79.c
bst29.c
cola61.c
cola83.c
cp41.c
cp53.c
cp79.c
cpp13.c
da73.c
example.c
fd19.c
fd23.c
fd47.c
fd53.c
fd97.c
fork79.c
mergesort47.c
mm19.c
mm23.c
mm53.c
mm59.c
mnmx67.c
mnmx71.c
nr13.c
pipe83.c
pipe97.c
pl53.c
pm73.c
pth23.c
pth47.c
rf13.c
th19.c
th59.c
th89.c

这表明输出是按 sortC 中的名称排序的。


第二轮

经过讨论,如果原始进程使用从 preC 的标准输出中读取的管道 fork 并执行 preC 进程,这似乎是最好的原始过程。那么原进程应该执行sortC进程。

为了支持这个练习,我创建了一个数据文件 data,其中包含:

abyssinian
yosemite
sierra
high
ocelot
jaguar
tiger
lion
leopard
snow leopard
puma
panther
cougar

我从源代码 fork31.c 创建了一个修改过的程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MSGSIZE 512

int main(void)
{
int p[2];

if (pipe(p) == -1)
{
perror("pipe call"); // from example code pipe2.c
exit(1);
}

switch (fork())
{
case -1:
perror("fork call"); // from example code pipe2.c
exit(2);
case 0: // child writes to pipe
dup2(p[1], STDOUT_FILENO); // redirect standard output and error output
close(p[0]); // close link
close(p[1]);
execl("./preC", "preC", (char *)0); // call execl() to execute pre.c
perror("execl() failed!");
return(EXIT_FAILURE);
default: // parent reads from pipe
{
close(p[1]);
int nbytes;
char inbuf[MSGSIZE];
while ((nbytes = read(p[0], inbuf, MSGSIZE)) > 0)
write(STDOUT_FILENO, inbuf, nbytes);
close(p[0]);
execl("./sortC", "sortC", (char *)0); // call execl() to execute sort.c
return(EXIT_FAILURE);
}
}
/*NOTREACHED*/

return(EXIT_FAILURE);
}

这接近问题中“下一次修订”中的修订代码。主要区别是使用 > 而不是 >= 来识别 EOF。使用低级(文件描述符)I/O 函数 read(),EOF 由读取的零字节指示; -1表示错误,EOF不是错误。我还使用 write() 将数据写入标准输出。

我更改了 preC shell 脚本以使用 ls -Ct *.c 来减少输出量。

调用的结果是:

$ fork31 < data
fork31.c pipe83.c cola61.c cp79.c mergesort47.c
fork79.c pth47.c cpp13.c th89.c mnmx67.c
pl53.c pth23.c fd19.c cp53.c mm19.c
da73.c bs79.c fd53.c th59.c mm53.c
example.c pm73.c fd23.c th19.c mm23.c
rf13.c nr13.c fd97.c cp41.c mm59.c
pipe97.c cola83.c fd47.c mnmx71.c bst29.c
abyssinian
cougar
high
jaguar
leopard
lion
ocelot
panther
puma
sierra
snow leopard
tiger
yosemite
$

当然,ls 的输出不再按二级排序。从 data 提供给 sortC 的姓名列表已按预期排序。请注意,如果 ls 从它的标准输入读取,这将不起作用——排序过程将没有数据要排序。幸运的是,ls 是一个数据生成器 — 它不读取其标准输入。

关于c - 我的代码应该将子输出发送给父级。两个进程 exec()。它只是卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46412031/

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