Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
133 views
in Technique[技术] by (71.8m points)

c - Fork never enters child's process

I'm writing a code that mimics a shell behavior, specifically & and |.

My function receives user commands, and checks if there's an & at the end, then the child process should run in the background and the parent should not wait for it to finish and continue executing commands.

Also it's supposed to check if there's a | in the input array and run two child processes while piping their stdin and stdout.

I have implemented the behavior for &, but whenever I compile and run my code, I only get the printf sentence from the parent's process.

I would like to hear ideas how to fix this, in addition I would appreciate any suggestions regarding the implementation of | (pipes) and how to prevent zombies.

int process_arglist(int count, char** arglist) {
int pid = fork();
printf("%d", pid);
switch (pid) {
case -1:
    fprintf(stderr, "ERROR: fork failed
");
    return 1;
    break;

case 0: // Son's proccess
    printf("I got to son");
    //check last arglist argument
    if (strcmp(arglist[count - 1], "&") == 0) {
        setpgid(0, 0);
        arglist[count - 1] = NULL;
        if (execvp(*arglist, arglist) < 0) {     //execute the command
            fprintf(stderr, "ERROR: execvp failed
");
            exit(1);
        }
    } else { //There's no & at the end, look for pipes
        int i = 0;
        while (i < count) {
            if (strcmp(arglist[i], "|") == 0) {
                int pid2 = fork();
                if (pid2 < 0) {
                    //fork failed, handle error
                }
                if (pid2 == 0) { // Son's proccess

                } else { //Parent's code

                }
            }
        }
    }
    break;
    //in case no & and no |, call execvp

default: //Parent's code
    printf("I go to parent");
    return 1;
    break;
}
return 0;

}

The output is always "I go to parent"

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I assume your code is for Linux or some other POSIX system. Read some good book on Linux programming (perhaps the old Advanced Linux Programming, freely downloadable, or something newer).

stdio(3) is buffered, and stdout and printf is often (but not always) line-buffered. Buffering happens for efficiency reasons (calling write(2) very often, e.g. once per output byte, is very slow; you should prefer doing write-s on chunks of several kilobytes).

BTW you'll better handle failure of system calls (see intro(2) and syscalls(2)) by using errno(3) thru perror(3) (or strerror(3) on errno). You (and the user of your shell) needs to be informed of the failure reason (and your current code don't show it).

I recommend to often end your printf format control strings with (this works when stdout is line-buffered) or to call fflush(3) at appropriate places.

As a rule of thumb, I suggest doing fflush(NULL); before every call to fork(2).

The behavior you observe is consistent with the hypothesis that some printf-ed data is staying in buffers (e.g. of stdout).

You could use strace(1) on your program (or on other ones, e.g. some existing shell process) to understand what system calls are done.

You should compile with all warnings and debug info (e.g. gcc -Wall -Wextra -g with GCC), improve your code to get no warnings, and use the debugger gdb (with care, it can be used on forking processes).

I'm writing a code that mimics a shell behavior

You probably are coding some shell. Then study for inspiration the source code of existing free software shells (most -probably all- Linux shells are free software).

I would appreciate any suggestions regarding the implementation of | (pipes) and how to prevent zombies.

Explaining all that requires a lot of space (several chapters of a book, or perhaps, an entire book) and don't fit here or on any other forum. So read a good Linux or POSIX programming book. Regarding pipes, read pipe(7) (it should be created with pipe(2) before the fork). Regarding avoiding zombie processes, you need to carefully call waitpid(2) or some similar call.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...