如何解决C:如何在 execv 之前通过管道将值从子进程传递到父进程?
在开始之前,我只想说这是我的一个学校作业。我真的快要完成了,除了好吧,因为我在这里,很明显,我遇到了一个问题:(。
首先我会解释我的任务想要什么:
作业要我用 C 创建一个命令行程序,允许用户输入 N 个 /bin/
命令(例如 > /bin/ps /bin/ls "/bin/which gcc"
)。一旦用户输入命令并按下回车键,父进程(父进程就是程序)将创建N个子进程(即输入的/bin/
个命令数=父进程将创建的子进程数) )。每个孩子将运行 N 个命令之一。所有子进程将同时运行,父进程等待每个子进程终止。
一旦子进程终止,父进程将打印命令是否成功执行(例如 "Command /bin/ps has completed successfully"
或 "Command /bin/ps has not completed successfully"
),一旦所有子进程终止,父进程将打印 "All done,bye!"
问题:
所以我设法让我的子进程同时运行,唯一的问题是我不确定如何从子进程通过管道传递命令的值(如 /bin/ps
或 /bin/which gcc
)到父进程打印出成功或不成功的消息。我试过将写管道放在我的 execv
上方,这允许我通过管道传输我想要的东西,但 execv 不会输出任何内容,我不能将管道代码放在我的 execv
下方,因为在那个情况,那么虽然我的 execv
输出会显示,但我的管道不会。我确实认为这可能是由于 close(1)
造成的,但将其注释掉并没有改变结果。
所以我想要实现的是这样的:
> /bin/ls "/bin/which gcc" /bin/domainname /bin/fake_command
Output:
/usr/bin/gcc
localdomain
Command /bin/which gcc has completed successfully
Command /bin/domainname has completed successfully
a.txt b.c
Command /bin/ls has completed successfully
Command /bin/fake_command has not completed successfully
All done,bye!
>
但现在,我得到:
> /bin/ls "/bin/which gcc" /bin/domainname /bin/fake_command
Output:
Command /bin/which gcc has completed successfully
Command /bin/domainname has completed successfully
Command /bin/ls has completed successfully
Command /bin/fake_command has not completed successfully
>
如您所见,execv
命令的 /bin/
输出未显示在输出中。
我已经尝试为与我面临类似问题的人进行搜索,但他们的解决方案都没有对我有用,这就是我在这里问的原因。如果您有任何不清楚的地方,请告诉我,我会尽力解释。
代码:
q1.c
#include "q1.h"
int main(int argc,char *argv[])
{
int
child_status,pipe_array[2];
pid_t child;
char *success_or_fail;
char *msg_buffer = malloc(CHAR_MAX);
if (msg_buffer == NULL)
{
return -1;
}
struct timespec tw = {.tv_sec = 0,.tv_nsec = 10000000L};
Tuple *process_tuple;
size_t tuple_size = sizeof(*process_tuple) + sizeof(pid_t) + sizeof(char *);
process_tuple = calloc(argc,tuple_size);
if (process_tuple == NULL)
{
return -1;
}
// if (pipe(pipe_array) == -1)
// {
// perror("pipe: ");
// return -1;
// }
for (int j = 1; j < argc; j++)
{
child = fork();
if (child == 0)
{
int
executed,num_of_words,num_of_chars;
char
string[strlen(argv[j]) + 1],*backup = argv[j];
snprintf(string,sizeof(string),"%s",argv[j]);
num_of_chars = get_num_of_chars(string);
num_of_words = get_num_of_words(string);
char *command[num_of_chars + 1];
preparing_the_command(num_of_words,string,command);
// close(pipe_array[0]);
// close(1);
// dup2(pipe_array[1],STDOUT_FILENO);
// write(pipe_array[1],backup,sizeof(backup));
process_tuple[j - 1].pid = getpid();
process_tuple[j - 1].command = backup;
printf(" %i-PID -> %i\n %i-Command -> %s\n\n",process_tuple[j - 1].pid,process_tuple[j - 1].command);
executed = execv(command[0],command);
nanosleep(&tw,0);
if (executed == -1)
{
exit(EXIT_FAILURE);
}
else
{
exit(EXIT_SUCCESS);
}
}
else if (child == -1)
{
perror("fork() failed: ");
exit(EXIT_FAILURE);
}
}
printf(" PID -> %i\n Command -> %s\n\n",process_tuple[0].pid,process_tuple[0].command);
// while ((child = waitpid(-1,&child_status,0)) != -1)
// {
// for (int o = 0; o < argc; o++)
// {
// printf(" PID -> %i\n Command -> %s\n\n",process_tuple[o].pid,process_tuple[o].command);
// }
// close(0);
// close(pipe_array[1]);
//
// dup2(pipe_array[0],STDIN_FILENO);
// char *recipient;
//
// read(pipe_array[0],recipient,sizeof(recipient));
// if (!(WIFEXITED(child_status) && (WEXITSTATUS(child_status) == 0)))
// {
// success_or_fail = "not completed successfully";
// }
// else
// {
// success_or_fail = "completed successfully";
// }
// snprintf(msg_buffer,CHAR_MAX,"Command %s has %s\n",success_or_fail);
// fputs(msg_buffer,stdout);
// }
fputs("All done,bye!\n",stdout);
free(msg_buffer);
return 0;
}
int get_num_of_chars(const char string[])
{
int
i = 0,num_of_chars = 0;
while (string[i++] != '\0')
{
if (string[i] != ' ' && string[i] != '\t')
{
num_of_chars++;
}
}
return num_of_chars;
}
int get_num_of_words(const char string[])
{
int
i = 0,num_of_words = 0;
bool is_not_separator = false;
while (string[i++] != '\0')
{
if (string[i] == ' ' || string[i] == '\t')
{
is_not_separator = false;
}
else if (!is_not_separator)
{
is_not_separator = true;
num_of_words++;
}
}
return num_of_words;
}
void preparing_the_command(int num_of_words,char string[],char *command[])
{
char *token;
for (int j = 0; j < num_of_words && (token = strtok_r(string," ",&string)); j++)
{
command[j] = token;
}
command[num_of_words] = (void *) NULL;
}
q1.h
#ifndef ASSIGNMENT2Q1_Q1_H
#define ASSIGNMENT2Q1_Q1_H
/***************
** LIBRARIES **
***************/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
/*************
** STRUCTS **
*************/
typedef struct
{
pid_t pid;
char *command;
} Tuple;
/*************************
** FUNCTION PROTOTYPES **
*************************/
int get_num_of_chars(const char string[]);
int get_num_of_words(const char string[]);
void preparing_the_command(int num_of_words,char *command[]);
#endif //ASSIGNMENT2Q1_Q1_H
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。