• linux进程


    pid_t fork(void) 父进程创建一个子进程,父进程和子进程的PCB完全相同,除了pid,具有相同的用户态代码和数据,占用不同的内存地址。

     1 #include<sys/types.h>
     2 #include<unistd.h>
     3 #include<stdio.h>
     4 #include<stdlib.h>
     5 int main() {
     6     const char *message;
     7     printf("before fork
    ");
     8     pid_t pid;
     9     pid = fork();
    10     if(pid < 0) {
    11         exit(-1);
    12     }   
    13     else if(pid == 0) {
    14         message = "child";
    15     }   
    16     else {
    17         message = "parent";
    18     }   
    19     int i = 0;
    20     while(i < 5) {
    21         printf("%d --> %s
    ",i,message);
    22         sleep(1);
    23         ++i;
    24     }
    25     return 0;
    26 }

    before fork
    0 --> parent
    0 --> child
    1 --> parent
    1 --> child
    2 --> parent
    2 --> child
    3 --> parent
    3 --> child
    4 --> parent
    4 --> child

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    父进程执行到9行,fork进入内核,创建一个子进程,子进程和父进程具有完全相同PCB(除了pid),用户态代码和数据以及进程的状态,但是占用不同的内存地址。

    子进程把父进程的代码从开头-->fork-->到结束全部copy过来。

    此时,父进程在内核等待返回,子进程因为具有相同的PCB和进程状态,所以子进程也处于等待返回状态(6-9行不再执行,但是具有父进程拥有的变量和资源)。等到CPU下次调用到父进程或子进程时,父进程返回子进程的pid>0,

    如果创建子进程失败,父进程返回的pid<0;子进程返回的pid=0;

    因为父子具有完全相同的代码,所以父子进程根据pid选择性执行if else的某个分钟。  超出if else 代码块的语句是父子进程都要执行的。

    进程的id getpid,进程的子进程,返回时用数组保存,进程的父进程,getppid。

    父进程fork一个子进程后,可以在子进程调用exec函数簇,调用新的进程会覆盖子进程的代码,从而执行,与父进程不同的代码任务。

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------

    僵尸进程:进程终止,会释放内存空间,但是内存中仍旧保留其PCB信息,以及进程终止的信息。如果父进程暂未对子进程调用wait或waitpid对他进行清理,则是僵尸进程。

    每个刚刚终止的进程,都是僵尸进程。

    父进程在子进程之前终止,父进程会变为init(id=1)进程,此进程会回收所有的子进程。

    子进程在父进程之前终止, 父进程结束后,系统会回收所有的资源。

    pid_t wait(int *status)

    pid_t waitpid(pid_t pid,int *status,int options)

    wait和waitpid可以获得子进程的终止信息,还可以使父进程阻塞等待子进程终止,达到进程间同步的作用。

    进程间通信

    每个进程各自有不同的用户地址空间,所以进程之间通信,要在内核开辟一块缓冲区,进程1把数据从用户空间拷贝到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制叫IPC(进程间通信)。

    几种典型的IPC:

    pipe(管道)

    FIFO

    互发信号

    管道:

    1,父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。

    2,父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

    3,父进程关闭管道读端,子进程关闭管道写端,管道是用环形队列实现的。

    4,两个进程通过一个管道只能实现单向通信。

    5,管道的写端关闭,数据被读完,read返回0.

    6,管道的写端没关闭,数据被读完,再次read阻塞。

    7,读端关闭,write会出错。

    8,读端没关闭,write写满再write会阻塞,直到read后有空位。

    FIFO和socket一样,都是内核的一种特殊文件,创建该文件,只是标志内核管道,但是磁盘上并没有数据块,几个进程可以在文件系统中读写某个共享文件,也可以给文件加锁来实现进程间同步。

  • 相关阅读:
    PHP中文字符串编码转换
    html表单样式, table隔行高亮, 长字符串自动换行
    PHP带重试功能的curl
    redis+crontab+php异步处理任务
    emoji表情初探
    iptables进行DNAT(目标地址转换)
    Linux作为路由器(一)
    nginx正向代理http(一)
    Linux Shell sort排序常用命令(转载)
    Zabbix添加自定义监控项(一)
  • 原文地址:https://www.cnblogs.com/afreeman/p/8543879.html
Copyright © 2020-2023  润新知