【linux高级程序设计】(第八章)进程管理与程序开发 3

回收进程用户空间资源

仅调用退出函数的进程属于一个僵死进程,没有释放进程控制块PCB。

 

void exit (int __status):退出进程。会以反序执行on_exit()和atexit()中注册的清理函数,刷新流缓冲区。执行成功没有返回值,参数status用来标识退出状态返回给父进程;否则返回-1。

void _exit (int __status):不调用任何祖册函数和直接退出进程。此函数调用后不会返回,而是传递SIGCHLD信号给父进程,父进程可以通过wait函数获得子进程结束的状态。该函数不处理标准I/O缓冲区

int atexit (void (*__func) (void)):告诉进程,在正常退出时执行注册的func函数。注册函数没有参数

int on_exit (void (*__func) (int __status, void *__arg), void *__arg):告诉进程,在正常退出时执行注册的func函数。注册函数有参数,第一个参数为退出的状态,第二个参数为用户的输入信息。

 

exit与return区别:

(1)return退出当前函数,exit()退出当前进程。在main函数中return(0)和exit(0)完成一样的功能。

(2)return仅从子函数中返回,并不退出进程。而exit()在子函数中会调用终止处理程序,关闭所有I/O流。

#include<stdio.h>

#include<unistd.h>

#include<string.h>

int test(void)

{

    printf("a\n");

    sleep(1);

    //exit(0);   //循环只执行一次

    return 0;   //死循环

}



int main(int argc, char * argv[])

{

    int i = 0;

    i++;

    printf("i=%d\n",i);

    while(1)

        test();

    return 0;

}

 

exit与_exit使用对比

#include<stdlib.h>

int main(int argc, char * argv[])

{

    printf("output\n");

    printf("content in buffer");   //注意没有回车,在缓冲区

    _exit(0);

}

_exit(0)只显示output

#include<stdlib.h>

int main(int argc, char * argv[])

{

    printf("output\n");

    printf("content in buffer");   //注意没有回车,在缓冲区

    exit(0);

}

exit(0)显示output和content in buffer

 

on_exit使用例子:

#include<stdlib.h>

void test_exit(int status, void *arg)

{

    printf("before exit()!\n");

    printf("exit %d\n", status);

    printf("arg=%s\n",(char*)arg);

}

int main()

{

    char *str="test";

    on_exit(test_exit,(void *)str);

    exit(4321);

}

 

回收内核空间资源

进程PCB的释放,由当前进程的父进程完成的。父进程可以显示的调用wait()waitpid()函数来完成。

__pid_t wait (__WAIT_STATUS __stat_loc):父进程阻塞式的等待该进程的任意一个子进程结束,回收子进程的内核进程资源。返回当前结束子进程的PID,退出状态存储在stat_loc中。

#define WIFSIGNALED(status)  __WIFSIGNALED(__WAIT_INT(status)) :宏,用来判断进程是否是因为收到信号后而退出的。如果是宏值为1.

#define WIFEXITED(status)   __WIFEXITED(__WAIT_INT(status)):宏,用来判断进程是否是正常退出的。如果是,宏值为1.

#include<stdio.h>

#include<unistd.h>

#include<sys/types.h>

#include<fcntl.h>

#include<string.h>

#include<stdlib.h>



extern int errno;

int main(int argc, char *argv[])

{

    pid_t pid_one, pid_wait;

    int status;

    if((pid_one = fork()) == -1)

        perror("fork");

    if(pid_one == 0)

    {

        printf("my pid is %d\n", getpid());

        sleep(20);

        exit(EXIT_SUCCESS);   //正常退出

    }

    else

    {

        pid_wait = wait(&status);   //等待子进程结束

        if(WIFEXITED(status))

            printf("wait on pid: %d, normal exit, return value is:%4x\n",pid_wait, WEXITSTATUS(status));

        else if(WIFSIGNALED(status))

            printf("wait on pid:%d, recive signal, return value is:%4x\n", pid_wait, WIFSIGNALED(status));

    }

    return 0;

}

 

__pid_t waitpid (__pid_t __pid, int * __stat_loc, int __options):等待指定子进程结束

  第一个参数为进程PID值。

    PID > 0 :表示等待进程的PID就是PID

    PID == -1 :表示等待任意子进程结束,相当于调用wait函数

    PID == 0 :表示等待与当前进程的进程组PGID一致的进程结束

    PID < -1 :表示等待进程组PGID是此值的绝对值的进程结束

  第二个参数为结束进程的结束状态。

  第三个参数为等待选项,可设置为

    0 :阻塞

    WNOHANG  1 :不阻塞等待          没有子进程退出将返回0, 否则返回子进程的PID。

    WUNTRACED 2 :报告状态信息

 

孤儿进程与僵死进程

孤儿进程:父进程先退出,导致子进程被init进程收养的进程为孤儿进程。即父进程更改为init,init进程负责在孤儿进程退出后回收他的内核空间资源。

僵死进程:进程已经退出,但是父进程还没有回收其内核空间资源PCB

#include<stdio.h>

#include<unistd.h>

#include<stdlib.h>



int main()

{

    pid_t pid;

    if((pid = fork()) == -1)

        perror("fork");

    else if(pid == 0)

    {

        printf("child_pid pid = %d\n", getpid());

    }

    sleep(3);

    system("ps");

    exit(0);

}

【linux高级程序设计】(第八章)进程管理与程序开发 3

此时1184为僵死进程。

 

你可能感兴趣的:(linux)