Linux学习之:进程的控制

创建一个进程都创建了哪些内容

1.进程的PCB块
2.进程的虚拟地址空间mm_struct
3.进程的页表
这三个一起才算完成了进程的创建!

为什么要有地址空间?(重要!)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

fork()创建子进程

进程调用fork,当控制转移到内核中的fork代码后,
内核做:
1.分配新的内存块和内核数据结构给子进程
2.将父进程部分数据结构内容拷贝至子进程
3.添加子进程到系统进程列表当中
4.fork返回,开始调度器调度

通常,父子代码共享,父子再不写入时,数据也是共享的

fork()返回值

子进程返回0,
父进程返回的是子进程的pid

写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意(是任意一方!)一方试图写入,便以写时拷贝的方式各自一份副本
因此发生写时拷贝后表面上看父子进程还是指向同一个地址同一个空间,其实子进程的地址已经被页表映射到其他地方去了!!在这里插入图片描述

fork常规用法

1.一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
2.一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数

fork调用失败的原因

1.系统中有太多的进程
2.实际用户的进程数超过了限制

在这里插入图片描述

进程终止

进程退出场景

代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常终止

进程常见退出方法

正常终止(可以通过 echo $? 查看进程退出码):
1.从main返回
2.调用exit
3._exit

在这里插入图片描述

exit()与_exit()

在这里插入图片描述

进程等待

进程等待必要性(重要!)

首先需要了解进程退出OS做了些什么
在这里插入图片描述
在这里插入图片描述

进程等待的方法

在这里插入图片描述

阻塞的本质

在这里插入图片描述

status状态码(重要!!!)

在这里插入图片描述
在这里插入图片描述

宏观理解waitpid

在这里插入图片描述

进程程序替换(重要!)

替换原理

在这里插入图片描述
在这里插入图片描述

如何替换?

在这里插入图片描述

替换函数

在这里插入图片描述
在这里插入图片描述

程序替换其实只有一个系统调用其他的都是进行封装过的

在这里插入图片描述

做一个简易的shell

主要是为了理解我们在命令行创建的进程都是bash的子进程,bash也是利用程序替换的方法让作为子进程的我们去执行自己的代码(这层理解很重要!!!)

在这里插入图片描述

在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

#define NUM 128
#define CMD_NUM 64

int main()
{
    char command[NUM];
    for( ; ; ){
        char *argv[CMD_NUM] = { NULL };
        //1. 打印提示符
        command[0] = 0; //用这种方式,可以做到O(1)时间复杂度,清空字符串
        printf("[who@myhostname mydir]# ");
        fflush(stdout);
        //2. 获取命令字符串
        fgets(command, NUM, stdin);
        command[strlen(command) - 1] = '\0'; //"ls\n\0"
        //printf("echo: %s\n", command);

        //"ls -a -b -c\0";
        //3. 解析命令字符串, char *argv[];
        //strtok();
        const char *sep = " ";
        argv[0] = strtok(command, sep);
        int i = 1;
        while(argv[i] = strtok(NULL, sep)){
            i++;
        }

        //4.检测命令是否是需要shell本身执行的,内建命令
        if(strcmp(argv[0], "cd") == 0){
            if(argv[1] != NULL) chdir(argv[1]);
            continue;
        }

        //5. 执行第三方命令
        if(fork() == 0){
            //child
            execvp(argv[0], argv);
            exit(1);
        }

        int status = 0;
        waitpid(-1, &status, 0);
        printf("exit code: %d\n", (status >> 8)&0xFF);

        //for(i=0; argv[i]; i++){
        //    printf("argv[%d]: %s\n", i, argv[i]);
        //}
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值