gpt4 book ai didi

c - 连接到 FIFO(命名管道)的程序挂起

转载 作者:太空宇宙 更新时间:2023-11-04 04:06:53 25 4
gpt4 key购买 nike

我正在尝试通过使用 mkfifo() 创建多个 FIFO 管道在操作系统 shell 项目中实现流水线。目前,程序似乎在打开第一个 FIFO 进行写入后挂起。此外,在工作目录上执行 ls 时会出现 FIFO。我在这种情况下使用 freopen() 是不是错了?

void execute_external()
{
int backgrounding = 0;
if (raw_command[strlen(raw_command)-1] == '&')
{
pmesg(2, "Backgrounding requested.\n");
raw_command[strlen(raw_command)-1] = '\0';
raw_command = realloc(raw_command, strlen(raw_command)-1);
backgrounding = 1;
}

int numCommands = 1;
char **commands;
commands = malloc(sizeof(char *));

if(strstr(raw_command, "|") != NULL)
{
numCommands = separate_pipeline_commands(commands);
}
else
{
commands[0] = malloc(strlen(raw_command) * sizeof(char));
commands[0] = raw_command;
}

int i;
char *fifo = malloc(MAXFIFOLEN);
for (i = 0; i < numCommands; i++)
{
char **parameters_array = malloc(strlen(commands[i]) * sizeof(char *));
int num_params;
num_params = str_to_str_array(commands[i], parameters_array);
pmesg(2, "Command is %s.\n", commands[i]);

if (numCommands > 1)
{
int j;
for (j = 0; j < numCommands - 1; j++)
{
sprintf(fifo, "fifo%i", j);
mkfifo(fifo, S_IWUSR | S_IRUSR );
}
}

pid_t pid = fork();

pmesg(2, "Process forked. ID = %i. \n", pid);
if (pid < 0)
{
fprintf(to_write_to, "Could not fork a process to complete the external command.\n");
exit(EXIT_FAILURE);
}
int status;
if (pid == 0) // This is the child process
{
pmesg(1, "input: [%s] output: [%s] input: %d, output: %d backgrounding is %d\n",input_file_name, output_file_name, redirect_input, redirect_output, backgrounding);
if (numCommands > 1 && i == 0) // we may be pipelining and this is the first process
{
sprintf(fifo, "%s%i", "fifo", i);
printf("Initial output: %s.\n", fifo);
freopen(fifo, "w", stdout);
//~ unlink(fifo);
}
else if (numCommands > 1 && i !=0 && (i != numCommands-1)) // we are pipelining and this is not the first or last process
{
sprintf(fifo, "%s%i", "fifo", i-1);
printf("Input for process %i: %s.\n", i, fifo);
freopen(fifo, "r", stdin);
//~ unlink(fifo);
sprintf(fifo, "%s%i", "fifo", i+1);
printf("Output for process %i: %s.\n", i, fifo);
freopen(fifo, "w", stdout);
//~ unlink(fifo_2);
}
else if (numCommands != 1 &&i == numCommands)
{
char *fifo = malloc(strlen("fifo")+2);
sprintf(fifo, "%s%i", "fifo", i);
freopen(fifo, "r", stdin);
free(fifo);
}
if(redirect_output == 1)
{
freopen(output_file_name, "w", stdout);
}
if(redirect_input == 1)
{
freopen(input_file_name, "r", stdin);
}
if (backgrounding != 0)
{
freopen("/dev/null", "w", stdout);
}
pmesg(2, "This is the child process, running execlp.\n");
pmesg(1, "Command: [%s]\n", parameters_array[0]);
if (execvp(parameters_array[0], parameters_array) < 0)
{
fprintf(to_write_to, "Could not execute the external command. errno: %i.\n", errno);
exit(EXIT_FAILURE);
}
else { pmesg(2, "Executed the child process.\n");}
}
else
{
if (backgrounding != 0)
{
enqueue(&process_queue, pid, clock(), 0, 0);
printQueue(process_queue);
}
if (backgrounding == 0) { while(wait(&status) != pid); }// Wait for the child to finish executing
}
pmesg(1, "The child has finished executing.\n");
free(parameters_array);
}
free(commands);
}

最佳答案

我在下面的代码中添加了一些注释,但 XAder 的摘要值得先阅读,以帮助在我详细挑剔之前了解全局。

我建议以非常长的形式写出您将为两个命令的管道执行的确切代码,然后是三个命令的管道的代码,然后是四个……然后然后在重复的代码周围放置一个循环。 (事实上​​你只有一个 fork() 向我表明你为两个命令而不是三个命令编写了代码。:)

希望这对您有所帮助。

/* if numCommands == 1 or 0, the rest is probably useless too
so this should guard the entire routine, not just the routine
that creates FIFOs */
if (numCommands > 1)
{
int j;
for (j = 0; j < numCommands - 1; j++)
{
char *fifo = malloc(strlen("fifo")+1); /* BUG #1 */
sprintf(fifo, "%s%i", "fifo", j); /* BUG #2 */
mkfifo(fifo, S_IWUSR | S_IRUSR );
free(fifo); /* messy */
}
}

/* Bug #1 The malloc(strlen()+1) is only good for "fifo", doesn't
actually allocate space for your number. Don't forget the
ascii NUL character at the end of the string. Add another +1. */
/* Bug #2 works for numCommands < 10; with 10 commands, you'll need to +2
for two characters, and so on */
/* messy -- maybe just have a 'char fifo[MAXFIFOLEN];' allocation,
and set MAXFIFOLEN to 255 or 4096 or something. No need to allocate
and free a simple little buffer a dozen times. */

pid_t pid = fork();

/* You should probably place fork() in a for loop; one new process
per command. Another choice is to write this whole routine recursively
which might be adding too many moving parts into one program */

pmesg(2, "Process forked. ID = %i. \n", pid);
/* Note that parent and child get different values of 'pid', so printing
the value of pid here may be very confusing */
int status;
if (fork < 0) /* BUG #3 fork() is a function; should be pid */
{
fprintf(to_write_to, "Could not fork a process to complete the external command.\n");
/* perror() is a wonderful routine! it helps users know _why_ something failed */
exit(EXIT_FAILURE);
}

if (pid == 0) // This is the child process
/* only ONE path below will ever execute; this is why your fork()
should be in a loop over numCommands, so each command's process
can get its own individual stdin and stdout hooked together */
{
pmesg(1, "input: [%s] output: [%s] input: %d, output: %d backgrounding is %d\n",input_file_name, output_file_name, redirect_input, redirect_output, backgrounding);
if (numCommands > 1 && i == 0) // we may be pipelining and this is the first process
{
char *fifo = malloc(strlen("fifo")+2);
sprintf(fifo, "%s%i", "fifo", i); /* could just be sprintf(fifo, "fifo%i", i); */
printf("Initial output: %s.\n", fifo);
freopen(fifo, "w", stdout);
//~ unlink(fifo);
free(fifo);
}
else if (numCommands > 1 && i !=0 && (i != numCommands-1)) // we are pipelining and this is not the first or last process
{
char *fifo = malloc(strlen("fifo")+2);
sprintf(fifo, "%s%i", "fifo", i-1);
printf("Input for process %i: %s.\n", i, fifo);
freopen(fifo, "r", stdin);
//~ unlink(fifo);
char *fifo_2 = malloc(strlen("fifo")+2);
sprintf(fifo_2, "%s%i", "fifo", i+1);
printf("Output for process %i: %s.\n", i, fifo);
freopen(fifo_2, "w", stdout);
//~ unlink(fifo_2);
free(fifo);
free(fifo_2);
}
else if (numCommands != 1 &&i == numCommands)
{
char *fifo = malloc(strlen("fifo")+2);
sprintf(fifo, "%s%i", "fifo", i);
freopen(fifo, "r", stdin);
free(fifo);
}

关于c - 连接到 FIFO(命名管道)的程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5038626/

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