• 《Unix&Linux系统编程》第三章学习笔记


    第3章 Unix/Linux进程管理

    3.1 多任务处理

    多任务处理指同时执行几个独立的任务。在单CPU系统中一次只能执行一个任务。多任务处理是通过在不同任务之间多路复用CPU的执行时间来实现的,即将CPU执行操作从一个任务切换到另一个任务,这种切换机制称为上下文切换。如果切换速度足够快,就给人一种同时执行所有任务的错觉,这种逻辑并行性成为并发。多个CPU的多处理系统中,可在不同的CPU上实时、并行执行多项任务。

    3.2 进程

    在操作系统中,任务也成为进程。进程是对映像的执行。每个进程用一个独特的数据结构表示,叫做进程控制块(PCB)任务控制块(TCB),可直接称为PROC结构体,它包含某个进程的所有信息。

    3.3 多任务处理系统

    1.type.h文件
    定义了系统常数和表示进程的简单PROC结构体。

    2.ts.s文件
    在32位GCC汇编 代码中可实现进程上下文切换。

    3.queue.c文件
    可实现队列和链表操作函数
    enqueue()函数:按优先级将PROC输入队列
    dequeue()函数:返回从队列或链表中删除的第一元素
    printList()函数:打印链表元素

    4.t.c文件
    定义MT系统数据结构、系统初始化代码和进程管理函数。

    3.4 进程同步

    指控制和协调进程交互以确保其正确执行所需的各项规则和机制。

    睡眠模式:
    某进程需要某些当前没有的东西,如申请独占一个存储区域、等待用户输入字符等。
    实现方法:在PROC结构体中添加event字段,实现ksleep(int event)函数

    唤醒操作:
    多个进程可能会进入休眠状态等待同一个事件,当某个等待时间发生时,另一执行实体(可能是进程或中断处理程序)会调用kwakeup(event)函数来唤醒处于休眠状态等待该事件值的所有程序。

    3.5 进程终止

    1、正常终止:进程调用exit(value),发出_exit(value)系统调用来执行在操作系统内核中的kexit(value)

    2、异常终止:进程因某个信号而异常终止
    (1)kexit()算法
    在Unix/Linux中,进程只有非常松散的父子关系,,进程可能随时死亡。大多数大型操作系统内核通过维护进程家族树来跟踪进程关系。
    (2)进程
    进程家族树通过PROC结构中的一对子进程和兄弟进程指针以二叉树的形式实现,如:

    PROC *child,*sibling,*parent;
    

    (3)等待子进程终止
    进程可调用内核函数来等待僵尸子进程:

    pid = kwait(int *status) //成功则返回僵尸子进程的pid,没有子进程则返回-1
    

    当进程终止时,将唤醒父进程:

    kwakeup(running->parent);
    

    3.6 MT系统中的进程管理

    • 用二叉树的形式实现进程家族树
    • 实现ksleep()和kwakeup()进程同步函数
    • 实现kexit()和kwait()进程管理函数
    • 添加“W”命令来测试和演示等待操作

    3.7 Unix/Linux中的进程

    1、进程来源
    操作系统启动时,内核的启动代码会强行创建一个PID=0的初始进程,初始化PROC内容,初始化系统后,P0复刻出一个子进程P1。
    2、INIT和守护进程
    当进程P1开始运行时,它将执行映像更改为INIT程序,P1就是INIT进程
    P1的大部分子进程都是用来提供系统服务,在后台运行,不与任何用户交互,被称为守护进程
    3、登录进程
    P1复刻了许多LOGIN进程,每个中断上一个用于用户登录。
    4、sh进程
    用户成功登录是,LOGIN进程获取用户的gid和uid,从而成为用户的进程,将目录更改为用户的主目录并执行列出的程序。
    5、进程的执行模式
    进程以内核模式(Kmode)用户模式(Umode)两种模式执行。

    3.8 进程管理的系统调用

    1、fork()

    int pid = fork();
    

    fork()创建子进程并返回子进程的pid,如果失败则返回-1。
    2、进程执行顺序
    fork()完成后,运行哪个进程取决于它们的优先级。
    3、进程终止
    正常终止:

    pid = wait(int *status);
    

    异常终止:

    kill -s signal_number pid
    

    4、等待子进程终止

    int pid = wait(int *status);
    int pid = waitpid(int pid,int *status,int options);
    

    5、subreaper进程

    prct1(PR_SET_CHILD_SUBREAPER);
    

    这样,init进程P1将不再是孤儿进程的父进程。
    6、exec()
    更改进程执行映像:

    int execve(const char *filename,char *const argv[],char *const envp[]);
    

    7、环境变量

    • SHELL:指定将解释任何用户命令的sh
    • TERM:指定运行sh时要模拟的终端类型
    • USER:当前登录用户
    • PATH:系统在查找命令时将检查的目录列表
    • HOME:用户的主目录

    3.9 I/O重定向

    • stdin:标准输入
      重定向:
    int fd = open("filename",O_RDOMLY);
    close(0);
    dup(fd);
    
    • stdout:标准输出
      重定向:
    close(1);
    open("filename",O_WRONLY|O_CREAT,0644);
    
    • stderr:标准错误

    3.10 管道

    管道是用于进程交换数据的单向进程间通信通道,有一个读取端和一个写入端。
    1、管道编程

    int pd[2];
    int r = pipe(pd);
    

    2、管道命令处理

    ps x |grep "httpd"
    cat filename | more
    

    3、命名管道—FIFO
    sh中:

    mknod mypipe p
    

    C程序中:

    int r = mknod("mypipe",S_IFIFO,0);
    

    实践:

    1、fork函数:

    2、进程执行顺序

    3、等待子进程终止

  • 相关阅读:
    GIF文件转换为头文件工具
    深夜杂想
    swift项目第十天:网络请求工具类的封装
    swift项目第九天:正则表达式的学习
    swift项目第八天:自定义转场动画以及设置titleView的状态
    swift项目第七天:构建访客界面以及监听按钮点击
    swift项目第六天:中间发布按钮的封装以及监听点击事件
    swift项目第五天:swift中storyBoard Reference搭建主界面
    swift项目第四天:动态加载控制器
    swift项目第三天:手写代码搭建主框架
  • 原文地址:https://www.cnblogs.com/weihehahaha/p/16772464.html
Copyright © 2020-2023  润新知