首先,是的,这是我班上的实验室活动,但我已经提交并为这项练习辩护了。我想知道的是,如果有另一种方法,一种更有效的方式来编写这段代码。
我们的任务是编写一个创建进程的代码,该进程创建一个子进程,然后创建另一个子进程,最后创建另一个子进程。
*编辑:我将需求分开并编号,以提高可读性:)
最后一个孩子将显示系统中正在运行的当前进程。
然后它的父母会要求一个单词,然后使用用户的输入创建一个文件。
然后它的父母会要求一个单词或短语,然后在你机器的库中找到它(假设我输入了hi,它应该找到并列出包含hi&其目录的文件。喜欢这个词应该不重要)
最后,主要父母只会打印其父ID。
以下是我的完整代码:
int main(void){
char fileName[30];
char phrase[30];
int pid = fork();
int fd[2];
pipe(fd);
if(pid==0){
printf ("CHILD1: I am the 1st child\n");
printf ("CHILD1: ID is %d \n", getpid());
printf ("CHILD1: Parent ID is %d \n", getppid());
int pid2 = fork();
if(pid2==0){
printf ("\t CHILD2: I am the 2nd child\n");
printf ("\t CHILD2: ID is %d \n", getpid());
printf ("\t CHILD2: Parent ID is %d \n", getppid());
int pid3 = fork();
if(pid3==0){
printf ("\t\t CHILD3: I am the 3rd child\n");
printf ("\t\t CHILD3: ID is %d \n", getpid());
printf ("\t\t CHILD3: Parent ID is %d \n", getppid());
execlp ("/usr/bin/top", "top", NULL);
}else if(pid3==-1){
printf ("ID is %d", getpid());
printf ("error");
exit(1);
}else{
wait(NULL);
printf ("\t CHILD2: Enter a filename: ");
scanf ("%s", fileName);
printf ("\t CHILD2: %s was succcessfully created!\n", fileName);
execlp ("/bin/touch", "touch", fileName, NULL);
}
}else if(pid2==-1){
printf ("ID is %d", getpid());
printf ("error");
exit(1);
}else{
wait(NULL);
int pid4 = fork();
if(pid4 > 0) {
printf ("CHILD1: Enter a pharse: ");
scanf ("%s", phrase);
close(fd[1]);
close(STDIN_FILENO);
dup2(fd[0],STDIN_FILENO);
execlp ("/bin/grep", "grep", phrase, NULL);
}else if (pid4 == 0) {
close(fd[0]);
close(STDOUT_FILENO);
dup2(fd[1],STDOUT_FILENO);
execlp ("/usr/bin/find", "find", NULL);
}else {
printf ("error");
}
}
}else if(pid==-1){
printf ("ID is %d", getpid());
printf ("error");
exit(1);
}else{
wait(NULL);
printf ("PARENT: I am the parent\n");
printf ("PARENT: ID is %d \n", getpid());
}
}
答案 0 :(得分:0)
您的代码在运行时和行数方面似乎相当有效,但是一个主要功能,深度嵌套,对尝试阅读和理解您所做的事情的人类几乎没有帮助。
考虑另一个成语:一个更模块化的,其中进程的祖先(恕我直言)更容易被评论者遵循。 (我也调用了ps而不是top,因此在该步骤中不需要键盘交互。)
我的方法更“高效”吗?可以说是不,虽然我更喜欢这种按功能运行的方法更直接的编码。父母和子女过程的链接是人为的,但当然你的任务也是如此。
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
/*
* run the passed function in a child process, and return
* from this function only if the child process runs and
* exits with status of 0.
*/
static void
run_func_in_child(void (*f)())
{
int status;
pid_t pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(1);
case 0: /* child */
(*f)();
break;
default: /* parent */
if (waitpid(pid, &status, 0) == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return;
}
fprintf(stderr, "child did not exit cleanly\n");
exit(1);
}
}
/*
* scanf would be simpler, but let's protect against buffer overruns
*/
static void
get_rsp(const char *prompt, char *buf, size_t blen)
{
int bl;
printf("%s: ", prompt);
fflush(stdout);
if (fgets(buf, blen, stdin) == NULL) {
if (ferror(stdin)) {
perror("read");
}
exit(1);
}
bl = strlen(buf);
if (bl > 0 && buf[bl - 1] == '\n') {
buf[bl - 1] = '\0';
}
}
static void
child_4()
{
execlp("/usr/bin/ps", "ps", "-www", "-e", "f", NULL);
perror("exec /usr/bin/ps");
exit(1);
}
static void
child_3()
{
char buf[256];
int fd;
run_func_in_child(child_4);
get_rsp("File name", buf, sizeof buf);
if (access(buf, F_OK) == 0) {
fprintf(stderr, "%s already exists\n", buf);
exit(1);
}
if ((fd = creat(buf, 0644)) == -1) {
perror("creat");
exit(1);
}
close(fd);
printf("Created empty file %s\n", buf);
exit(0);
}
static void
child_2()
{
char buf[80];
int fd[2];
pid_t pid;
run_func_in_child(child_3);
get_rsp("Phrase", buf, sizeof buf);
if (pipe(fd) == -1) {
perror("pipe");
exit(1);
}
pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(1);
case 0:
/* no explicit wait for this child-of-child
* process, but when its parent (the grep) exits,
* init becomes the parent, and does the wait
*/
dup2(fd[1], 1);
close(fd[0]);
close(fd[1]);
execlp("/usr/bin/find", "find", NULL);
perror("exec of find");
exit(1);
default:
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
execlp("/usr/bin/grep", "grep", buf, NULL);
perror("exec of grep");
exit(1);
}
}
static void
child_1()
{
run_func_in_child(child_2);
printf("Child 1: pid is %d; ppid is %d\n", getpid(), getppid());
exit(0);
}
int
main(int ac, char *av[])
{
run_func_in_child(child_1);
return 0;
}