Linux系统编程之进程学习

进程相关概念

1.什么是程序,什么是进程,有什么区别?

程序是静态的概念,gcc   xxx.c -o  pro生成的pro文件叫做程序,进程是程序的一次运行活动,就是程序跑起来系统中多了一个进程,每个进程都一个非负整数表示唯一ID,叫pid

        pid = 0  交换进程(swapper) 作用:进程调度
        pid = 1  init进程                         作用:系统初始化


一、进程创建

1.使用fork函数创建

        pid_t fork(void);

        fork函数调用成功,返回两次

        返回值为0,     代表当前进程是子进程

        返回值非负数,代表当前进程为父进程,且返回值是子进程的ID 号码

        调用失败,返回-1

#include<stdio.h>

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



int main()
{
        pid_t pid;
        pid_t pid2;
        pid_t returnpid;
        pid = getpid();
        printf("befer print:%d\n",pid);

        returnpid = fork();

        pid2 = getpid();
        printf("after print:%d\n",pid2);

        if(pid == pid2){

                printf("this father print:%d   returnpid=%d\n",getpid(),returnpid);
        }else{

                printf("this child print:%d    returnpid=%d\n",getpid(),returnpid);
        }


        return 0;
}

运行结果

befer pint:8173
after print:8173
this father print:8173   returnpid=8174
after print:8174
this child print:8174    returnpid=0

fork之前的代码只有父进程再执行,fork之后的代码父进程子进程各自拥有一份,父进程子进程都会运行一次,至于谁先运行取决进程的调度。

2.使用vfork函数创建进程

vfork创建进程与fork的区别:

1.vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。

2.vfork 直接使用父进程存储空间,不拷贝,父进程的变量可以被子进程改变。

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
main()
{
        int cnt = 0;
        pid_t pid;
        pid_t pid2;
        pid = vfork();

        if(pid > 0 ){
                while(1){

                        printf("this father print:%d\n",getpid());
                        sleep(1);
                        printf("cnt=%d\n",cnt);
                }
        }else if(pid == 0){
                while(1){
                        printf("this child print:%d\n",getpid());
                        sleep(1);
                        cnt++;
                        if(cnt == 3){

                                exit(0);
                        }
                }
        }

        return 0;

        运行结果:等待子进程退出(使用正常退出)后,父进程才会执行,子进程使用父进程存储空间改变了父进程cnt的值

this child print:8680
this child print:8680
this child print:8680
this father print:8679
cnt=3
this father print:8679
cnt=3
this father print:8679
cnt=3
this father print:8679

二、进程创建目的

一个父进程希望复制自己,使父子进程同时执行不同的代码段。在网络服务器进程中,父进程等待客户端连接请求,当请求到达父进程调用fork,使得子进程处理请求,父进程继续等待下一个请求到来。前期是子进程代码全部copy父进程,后期是写操作copy。

 三、进程退出

1.正常退出

        1.Main函数调用return

        2.进程调用exit(),标准c库

        3.进程调用_exit()或者_Exit(),属于系统调用

        补充:

        1.进程最后一个线程返回

        2.最后一个线程调用pthread_exit

2.异常退出

        1.调用abort

        2.当进程收到某些信号时,如ctrl+C

        3.最后一个线程对取消(cancellation)请求做出响应

四、等待子进程退出

1.为什么要等待子进程退出

        创建子进程执行时,想要知道子进程执行情况如何(活干完没,没干完是什么原因),此时父进程需要等待子进程退出并且收集子进程的退出状态。活干完了是正常退出根据状态码判断活干怎么样,活没干完就是异常退出根据退出状态码判断原因。子进程退出状态不被收集会变成僵死进程(僵尸进程)。

子进程调用exit函数,父进程调用wait函数收集退出状态,  wait(&status),再用以下宏来解析结果

 除了调用wait函数来收集退出状态,还可以使用waitpid,区别在于wait使使用者阻塞,waitpid有一个选项,可以使调用者不阻塞。相关函数原型如下

status参数:是一个整型数指针
               非空:子进程退出状态放在它所指向的地址中。
                空:不关心退出状态

通常使用pid>0

 通常使用WNOHANG,挂起方式不阻塞

五、孤儿进程

进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程

Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

猜你喜欢

转载自blog.csdn.net/qq_44848795/article/details/122738855