gpt4 book ai didi

c - 管道和流程

转载 作者:太空狗 更新时间:2023-10-29 17:20:14 27 4
gpt4 key购买 nike

前提:编写程序向用户查询两个输入字符串。每个输入字符串应该是一个 unix 命令,允许有参数。例如,输入 1 可以是 ls -l,输入 2 可以是 more。然后该程序将创建一个管道和两个子进程。第一个子进程将运行第一个输入中指定的命令。它将输出到管道而不是标准输出。第二个子进程将运行第二个输入中指定的命令。它将从管道而不是标准输入获取输入。父进程将等待它的两个子进程完成,然后整个过程将重复。当输入“@”符号作为第一个命令时,执行将停止。这是我的代码:

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

int main(){

/* Program Termination Symbol */
const char terminate = '@';

/* String delimiter */
const char delimiter = ' ';

/* Pipe file ID's */
int fileID[2];

/* Parent ID's */
int pid1, pid2;

/* String token */
char * token, * token2;

/* User input */
char * user_input, line[100];

user_input = (char *) malloc(100);

/* Unix Commands */
char * command1[10], *command2[10];

for (int i=0; i<10; i++)
{
command1[i] = (char *)malloc(100*sizeof(char));
command2[i] = (char *)malloc(100*sizeof(char));
}

/* Begin main program logic */

printf("Please enter the first command: \n");

user_input = gets(line);

while (user_input[0] != terminate)
{
token = (char *) malloc(100*sizeof(char));

for (int i=0; i<10; i++)
{
if (i == 0)
{
token = strtok(user_input, &delimiter);
} else {
token = strtok(NULL, &delimiter);
}

if (token != NULL)
{
strcpy(command1[i], token);
} else {
command1[i] = 0;
}
}

printf("Please enter the second command: \n");
user_input = gets(line);

token2 = (char *) malloc(100*sizeof(char));

for (int i=0; i<10; i++)
{
if (i == 0)
{
token2 = strtok(user_input, &delimiter);
} else {
token2 = strtok(NULL, &delimiter);
}

if (token2 != NULL)
{
strcpy(command2[i], token2);
} else {
command2[i] = 0;
}
}


/* Pipe and execute user commands */

/* Create pipe */
pipe(fileID);

/* Create child processes */

pid1 = fork();

if (pid1 != 0)
{
pid2 = fork();
}

/* First child process */
if (pid1 == 0)
{
dup2(fileID[1], 1);
execvp(command1[0], command1);
}

/* Second child process */
if (pid2 == 0)
{
dup2(fileID[0], 0);
execvp(command2[0], command2);
}

/* Wait for children to terminate */
wait(&pid1);
wait(&pid2);

/* Repeat */
printf("Please enter the first command: \n");
user_input = gets(line);
}

return 0;
}

我遇到的问题是我的等待。如果我有两个,这对我来说是有意义的(每个 child 一个等待)然后程序在执行第一个管道后卡住。如果我删除第二个等待,程序将再次开始循环,但不会接受除 enter 之外的键盘输入,并会产生段错误。因此,对于这两种等待,输入和输出是...

Please enter the first command:
ls
Please enter the second command:
more
Pipe
Pipe.c
Pipe.c~

...然后它锁定了。如果我删除第二个等待,输入/输出是...

Please enter the first command:
ls
Please enter the second command:
more
Pipe
Pipe.c
Pipe.c~
Please enter the first command:
(I hit enter, nothing else will work)
Segmentation fault

有人有什么建议吗?这显然与等待两个进程有关,但我不知道如何处理它。


此程序现已 100% 正常运行 - 非常感谢大家的帮助! Stack Overflow 一直是互联网上最好的资源之一。非常感谢大家花时间查看我的代码并给我建议。

最佳答案

我同意 torak 所说的一切,但要解决您的问题,您需要关闭管道。我认为你在“悬着”,因为管道仍然打开。

所以在父级中,就在“等待”之前,我会关闭管道。

close(fileID[0]);
close(fileID[1]);
wait(&pid_status);
wait(&pid_status);

然后,就在每个 execvp 之前,我会关闭 child 不会使用的管道的末端:

close(fileID[0]);
dup2(fileID[1], 1);
execvp(command1[0], command1);


close(fileID[1]);
dup2(fileID[0], 0);
execvp(command2[0], command2);

这应该可以解决您的吊死问题。除了 torak 提出的建议之外,我还建议使用 fgets 而不是 gets 来防止缓冲区溢出。

关于c - 管道和流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3523481/

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