僵尸进程 & 孤儿进程 & UNIX异常控制流相关函数

僵尸进程(Zombie Process):子进程结束,父进程没有等待(即没有调用wait/waitpid函数)它,那么它成为僵尸进程

孤儿进程(Orphan Process):一个父进程退出,而它一些子进程还在运行中,那么这些子进程将成为孤儿进程;孤儿进程将被init进程收养,即init进程为其父进程

父进程退出时,若它的某些子进程为僵尸进程,那么这些僵尸进程也退出。因而在系统中,若想杀死僵尸进程,其中的一个办法就是杀死其父进程。

下面这个例子演示的就是僵尸进程,在运行的时候,可以用"ps -ef | grep defunct"进行查看。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t pid;

    if ((pid = fork()) == 0) {
        printf("If my parent doesn't wait me, I will be a zombie.\n");
        exit(0);
    } else {
        printf("%d\n", pid);
        // use "ps -ef | grep defunct" to find the zombie
        sleep(10);
        wait(NULL);
        // after wait function, if you use "ps -ef | grep defunct" to find the zombie
        // you will find none
        sleep(10);
    }
}

父进程与子进程拥有独立的虚拟空间,因而对于像全局变量、静态变量、动态内存(堆)、局部变量(栈)等都是自己有单独的一份,不是共享的,因而互不影响。

下面的程序可以验证:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

int a = 0;
int main()
{
    static int b = 10;
    char* ptr = (char*)calloc(sizeof(char)*100, 0);
    ptr[0] = 'A';
    ptr[1] = 'B';
    a = a + 1;
    if (!fork()) {
        ptr[0] = 'a';
        ptr[1] = 'b';
        printf("%s\n", ptr);
        free(ptr);
        printf("%d\n", a + 2);
        printf("%d\n", b + 2);
        //while (1);
        exit(0);
    }
    wait(NULL, 0);
    printf("%d\n", a);
    printf("%d\n", b);

    printf("%s\n", ptr);
    free(ptr);
    return 0;
}

通过“man 7 signal” 可以查看诸如SIGINT, SIGKILL, SIGTSTP, SIGCHLD, SIGTERM等信号的意义。

#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);
                                    Returns: PID of either the caller or the parent
#include <stdlib.h>
void exit(int status); This function does not return
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);
                           Returns: 0 to child, PID of child to parent, −1 on error
#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);
                          Returns: PID of child if OK, 0 (if WNOHANG) or −1 on error

waitpid 函数及其参数详解:

By default (when options = 0), waitpid suspends execution of the calling process until a child process in its wait set terminates. If a process in the wait set has already terminated at the time of the call, then waitpid returns immediately.In either case, waitpid returns the PID of the terminated child that caused waitpid to return, and the terminated child is removed from the system.

If pid > 0, then the wait set is the singleton child process whose process ID is equal to pid.
If pid = -1, then the wait set consists of all of the parent’s child processes.

The default behavior can be modified by setting options to various combinations of the WNOHANG and WUNTRACED constants:
. WNOHANG: Return immediately (with a return value of 0) if none of the child processes in the wait set has terminated yet. The default behavior suspends the calling process until a child terminates. This option is useful in those cases where you want to continue doing useful work while waiting for a child to terminate.
. WUNTRACED: Suspend execution of the calling process until a process in the wait set becomes either terminated or stopped. Return the PID of the terminated or stopped child that caused the return. The default behavior returns only for terminated children. This option is useful when you want to check for both terminated and stopped children.
. WNOHANG | WUNTRACED: Return immediately, with a return value of 0, if none of the children in the wait set has stopped or terminated, or with a return value equal to the PID of one of the stopped or terminated children.

If the status argument is non-NULL, then waitpid encodes status information about the child that caused the return in the status argument. The wait.h include file defines several macros for interpreting the status argument:
. WIFEXITED(status): Returns true if the child terminated normally, via a call to exit or a return.
. WEXITSTATUS(status): Returns the exit status of a normally terminated child. This status is only defined if WIFEXITED returned true.
. WIFSIGNALED(status): Returns true if the child process terminated because of a signal that was not caught.
. WTERMSIG(status): Returns the number of the signal that caused the child process to terminate. This status is only defined if WIFSIGNALED(status) returned true.
. WIFSTOPPED(status): Returns true if the child that caused the return is currently stopped.
. WSTOPSIG(status): Returns the number of the signal that caused the child to stop. This status is only defined if WIFSTOPPED(status) returned true.

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
                                          Returns: PID of child if OK or −1 on error
#include <unistd.h>
unsigned int sleep(unsigned int secs); Returns: seconds left to sleep
#include <unistd.h>

int pause(void);
                                                                   Always returns −1
#include <unistd.h>

int execve(const char *filename, const char *argv[], const char *envp[]);
                                          Does not return if OK, returns −1 on error
#include <stdlib.h>
char *getenv(const char *name); Returns: ptr to name if exists, NULL if no match
#include <stdlib.h>
int setenv(const char *name, const char *newvalue, int overwrite); Returns: 0 on success, −1 on error void unsetenv(const char *name); Returns: nothing
#include <unistd.h>

pid_t getpgrp(void);
                                         Returns: process group ID of calling process
#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);
                                                   Returns: 0 on success, -1 on error

setpgid 函数及其参数详解:

The setpgid function changes the process group of process pid to pgid. If pid is zero, the PID of the current process is used. If pgid is zero, the PID of the process specified by pid is used for the process group ID. For example, if process 15213 is the calling process, then

            setpgid(0, 0);

creates a new process group whose process group ID is 15213, and adds process 15213 to this new group.

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig); Returns: 0 if OK, −1 on error
#include <unistd.h>
unsigned int alarm(unsigned int secs); Returns: remaining secs of previous alarm, or 0 if no previous alarm
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(
int signum, sighandler_t handler); Returns: ptr to previous handler if OK, SIG_ERR on error (does not set errno)

There are two signals which cannot be intercepted and handled: SIGKILL and SIGSTOP.
#include <signal.h>
int sigaction(int signum, struct sigaction *act, struct sigaction *oldact); Returns: 0 if OK, −1 on error
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); Returns: 0 if OK, −1 on error int sigismember(const sigset_t *set, int signum); Returns: 1 if member, 0 if not, −1 on error
#include <setjmp.h>
int setjmp(jmp_buf env); int sigsetjmp(sigjmp_buf env, int savesigs); Returns: 0 from setjmp, nonzero from longjmps
#include <setjmp.h>
void longjmp(jmp_buf env, int retval); void siglongjmp(sigjmp_buf env, int retval); Never returns

posted on 2012-10-29 14:12  NULL00  阅读(1419)  评论(0编辑  收藏  举报

导航