进程api与控制

进程创建

 创建进程:
     pid_t fork(void);
 返回值:
    失败 -1, 成功返回两次,在父进程中返回值为子进程ID,在子进程中返回父进程ID
 注:
    子进程的代码和父进程的代码是一致的,但是子进程启动之后是从fork之后开始执行的


 获得pid,进程id,获得当前进程:
    pid_t fork(void);


 获得当前进程父进程的id
    pid_t getppid(void);

进程创建示例代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    printf("Begin ....\n");
    pid_t pid = fork();
    if(pid < 0){
        perror("fork err");
        exit(1);
    }
    if(pid == 0){
        //子进程
        printf("I am a child,pid = %d,ppid=%d\n",getpid(),getppid());
        while(1){
            printf("I am a child\n");
            sleep(1);
        }
    }
    else if(pid > 0){
        //父进程的逻辑
        printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
        while(1){
            sleep(1);
        }
    }
    printf("End ....\n");
    return 0;
}

代码示例 用父进程创建N个子进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int n = 5;
    int i =0;
    pid_t pid = 0;
    for(i = 0; i < 5 ; i ++){//父进程循环结束
        pid = fork();
        if(pid == 0){
            //son 
            printf("I am child ,pid=%d,ppid=%d\n",getpid(),getppid());
            break;//子进程退出循环的接口 , 否则子进程也会创建自己的子进程,因为fork是在一个循环中的
        }else if(pid > 0){
            //father 
            printf("I am father,pid=%d,ppid=%d\n",getpid(),getppid());
        }
    }
     sleep(i);
    if(i < 5){
        printf("I am child ,will exit,pid=%d,ppid=%d\n",getpid(),getppid());
    }
    else{
        //father
        printf("I am parent,will out pid=%d,ppid=%d\n",getpid(),getppid());
    }
    return 0;
}


进程共享

父子进程之间在fork后。有哪些相同,哪些相异之处呢?
fork之后:

父子进程相同之处:全局变量、.data(数据块)、.text(代码块)、栈、堆、环境变量、用户ID、宿主目录、进程工作目录,信号处理方...
父子进程不同之处:进程ID、fork返回值、父进程ID、进程运行时间、闹钟、未解决信号集
那么子进程复制了父进程的用户空间内容,已经父进程的PCB,但pid不同。子进程每fork一次都要将父进程的地址空间完全拷贝一份,然后映射至物理内存吗?
答案是不是的。父子进程间遵循读时共享写时复制的原则,这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。

关于全局变量,子进程虽然是也拥有同样的全局变量,但是父子进程的内存是独立的,所以不会有竞争问题
代码示例 父子进程不共享全局变量:

#include <stdio.h>
#include <unistd.h>

int var = 100;

int main()
{
    pid_t pid = fork();
    if(pid == 0){
        //son 
        var = 1001;
        printf("address = %d var = %d,child,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
        sleep(3);
        printf("address = %d var = %d,child,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
    }
    else if(pid > 0){
        //parent 
        sleep(1);//保障子进程能够修改var的值成功
        printf("address = %d var = %d,parent,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
        var=2000;
        printf("address = %d var = %d,parent,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
    }
    return 0;
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.内存的页面置换算法 (1)最佳置换算法(OPT)(理想置换算法):从主存中移出永远不再需要的页面;如无这样的...
    杰伦哎呦哎呦阅读 3,366评论 1 9
  • Linux 进程管理与程序开发 进程是Linux事务管理的基本单元,所有的进程均拥有自己独立的处理环境和系统资源,...
    JamesPeng阅读 2,517评论 1 14
  • 1 进程介绍 1.1 进程和程序 所谓进程是由正文段(text)、用户数据段(user segment)以及系统数...
    疯狂小王子阅读 1,273评论 0 7
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,161评论 1 32
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,897评论 0 27