进程基础知识(创建、pid获取)

getpid():获得子进程的pid
getppid():获得父进程的pid

执行可执行程序的时候,就会创建一个进程
一、创建子进程:

1、 fork函数:用于创建一个子进程(当前进程的子进程) ——<unistd.h>
        pid_t fork(void) 
    一次fork调用:由一个进程变成两个进程------->两个进程各自对fork返回

返回2个值:    1)返回子进程的pid(>0)  (父进程的返回)  
              2)返回0               (子进程的返回)

注:C语言中,一个函数返回多个值,需用到输出参数

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void){
    pid_t pid;
    char *message;
    int n;

    pid = fork();

    if(pid < 0){
        perror("fork");
        exit(1);
    }

    if(pid == 0){
        message = "child process!!!";
        n = 6;
    }else{
        message = "parent process!!!";
        n = 3;
    }

    for(; n > 0; n--){
        printf("%s\n", message);
        sleep(1);
    }
    
    return 0;
}

shell抢占:

注:shell也是一个进程,他也会抢占资源。

(1)pid是一直往上加,直到不能再加再往回找;但是文件描述符是每次都找可用的最小的fd

2、父子进程的执行内容

fork函数前的代码子进程不执行,子进程接着fork函数之后的代码执行

fork函数执行后函数会出现分支,一个进程分两个分支

3、循环创建子进程的架构
注:子进程与父进程权限一样,处于相同的地位去争夺CPU
循环创建5个进程:使用for循环

int main(void)
{
    int i;
    pid_t pid;
    printf("ccccccccccccccccc\n");
    
    for(i = 0; i < 5; i++)
    {
        pid = fork();
        if(pid == -1)
        {
            perror("fork error");
            exit(-1);
        }else if(pid == 0){
            break; //防止子进程再次创建子进程
        }
    }
    
    if(i < 5)
    {
        sleep(i);
        printf("%d child process, pid = %d \n", i+1, getpid());
    }else{
        sleep(i);
        printf("parent process  ppid = %d \n", getppid());
    }
    
    return 0;    
}

特别注意: 

代码执行分析:父进程和子进程处于相同的地位去争夺CPU,谁抢到CPU谁执行
1)父进程每次返回子进程的pid,因此大于零,每次都不执行循环内容,只是进行i++;循环结束后,执行下方的代码
2)子进程返回值为0,每次进入循环体执行后,break,执行下面的if语句
3)程序中加入的sleep函数为了控制进程执行的顺序,若去掉sleep,则进程结束顺序不定
4)在去掉所有的sleep函数后,在原有的进程集中,又加入shell进程来争夺资源,shell进程在等待./a.out进程结束抢占前台资源

二、获得用户id和组id
uid:
uid_t getuid(void):获得当前进程实际的uid
uid_t geteuid(void):获得当前进程有效的用户id

gid:
gid_t getgid(void):获得当前进程使用的用户组id
gid_t getegid(void):获得当前进程有效的用户组id

三、父子进程共享:原则:读时共享,写时复制
fork函数之前的代码,子进程不执行
fork函数执行之后:

父子进程:
相同之处:(全局变量、.data、.text)、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式
不同之处:进程ID、fork返回值、父进程ID、进程运行时间、定时器、未决信号集
注:父子进程间的全局变量是各有一份,各自独享

(全局变量、.data、.text)、栈、堆:父子进程读时共享同一块物理地址,写时复制
1、似乎,子进程复制了父进程0-3G用户空间内容,以及父进程的PCB,但pid不同。真的每fork一个子进程都要将父进程的0-3G地址空间完全拷贝一份,然后再映射至物理内存吗?

当然不是!父子进程间遵循读时共享写时复制的原则。这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。

2、父子进程的共享内容:1、文件描述符
                                          2、父子进程共享mmap建立的映射区

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star星屹程序设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值