读书笔记-APUE第三版-(8)进程控制

读书笔记-APUE第三版-(8)进程控制

进程ID

每一个进程都有一个唯一的进程ID。几个特殊进程:

  1. 0号进程是内核进程,一般是调度进程swapper。
  2. 1号进程init,是用户进程(以root权限执行/sbin/init),负责初始化。
  3. 几个重要函数:getpid(进程ID)/getppid(父进程ID)/getuid(进程真有用户ID)/geteuid(进程有效用户ID)/getgid(进程真有用户组ID)/getegid(进程有效用户组ID)。

fork/exec/wait例程

fork家族函数用于创建子进程(父子进程关系下节详细介绍),子进程往往调用exec家族函数运行新程序(fork+exec操作在有些系统中被称为spawn孵化),而wait家族函数用于获取子进程终止状态。

system函数使用/bin/sh运行命令,下面是使用fork/exec/wait实现的简单版本号

#include<sys/wait.h>
#include<errno.h>
#include<unistd.h>
int system(constchar *cmdstring) /* version without signal handling */
{
    pid_t pid;
    int status;
    if (cmdstring == NULL)
        return(1); /* always a command processor withUNIX */
    if ((pid = fork()) < 0) {
        status = -1;
    } else if (pid == 0) { /* fork返回值为0,表示是在子进程中*/
        execl("/bin/sh", "sh","-c", cmdstring, (char *)0);
        _exit(127); /* execl error */
    } else { /* 在父进程中,fork返回子进程pid */
        while (waitpid(pid, &status, 0) < 0) {
            if (errno != EINTR) {
                status = -1; /* error other than EINTR fromwaitpid() */
                break;
            }
        }
    }
    return(status);
}

  1. fork函数一次调用,在父进程和自己成中两次返回,由于父进程能够fork多个子进程,所以设计成在父进程中返回子进程pid,而在子进程返回0,由于子进程能够通过getpid和getppid获取自身pid和父进程pid。常见应用场景是在网络编程中,父进程while循环监听用户请求,当接收到用户请求,fork出子进程进行处理。注:linux系统中,fork通过clone系统调用实现。
  2. waipid函数使用參数0等待指定子进程返回,wait函数家族包含wait(等待任一子进程返回)/waitpid(等待指定子进程&组返回,并能通过第三个參数设置堵塞选项)/waittid(进一步扩展,能获取导致进程终止的信号信息等)/wait3(还能够返回进程使用的资源)/wait4(其它wait函数的入口)。
  3. exec家族函数的作用是替换掉当前进程上下文(text/data/heap/stack等),运行新的程序(不会创建新进程)。exec家族函数包含execl/execlp/execle/execv/execvp/execve,各个函数主要差别在參数上,当中l表示是列表形式,v表示是指针数组形式,e表示环境变量,p表示命令參数是相对路径,会在PATH路径中搜索。

父子进程

子进程和父进程共享仅仅读的text段,针对bss段、对、栈,现代操作系统使用COW(copy-on-write)技术,仅仅有发生改变时,才会拷贝对应的内存页。

父子进程关系

子进程会继承父进程的大量属性,当中一些重要属性包含:真实/有效用户信息,进程组/会话信息,工作文件夹,环境变量,资源限制等。

父子进程最明显的差别是:子进程的tms时间统计信息被清零,子进程不会继承文件锁,未决闹钟&信号等(兴许章节讨论)。

子进程和父进程返回先后顺序是不确定的,假设用户程序对父子进程运行顺序有依赖,须要自行处理,比方使用信号实现等待通知机制等。

  1. 内核为每一个正在终止的进程保留了少量信息(pid,终止状态,CPU时间等),便于父进程获取其终止状态。
  2. 假设子进程在父进程之前结束,而父进程没有wait,子进程会变成僵尸进程。
  3. 假设父进程先结束,子进程的父进程会变成init进程(pid为1),所以假设要避免僵尸进程的产生,能够两次调用fork,即在子进程中再次调用fork,然后退出。这样第二个fork出来的进程因为其父进程退出,所以被init进程接管。

文件共享

子进程会dup父进程打开的文件描写叙述符(共享文件描写叙述符close-on-exec标记),包含标准输出、输入和错误输出。

<span>读书笔记-APUE第三版-(8)进程控制</span>

如图,父子进程共享file tableentry,位置偏移量一致,所以要父子进程读写同一文件时要注意同步。

设置进程用户ID

之前提到,子进程会继承父进程的uid和euid(有效用户ID),能够调用setuid(setgid)改动进程用户(组)。

  1. 假设是root用户调用,会同一时候改动进程的uid、euid和备份euid(saved set-user-id)。登陆后,由login(root进程)设置用户ID。
  2. 非root用户仅仅能改动euid,并且仅仅能改动成之前的uid或者备份euid,否则出错。
  3. 假设自进程运行exec方法,并且运行程序的set-user-ID位被设置,那么euid被设置被运行程序属主ID。
  4. 备份euid复制euid。正常情况下,uid=euid=备份euid。
  5. 程序编写遵循“最小权限“模型,当且仅当程序须要高权限时,才调用setuid提升权限,操作完之后再调用setuid恢复权限。

其它进程相关函数

  1. 进程审计:acct开启进程审计功能,系统记录已终止进程的统计信息,包含用户ID,启动时间,CPU时间等。Linux系统审计记录保存在/var/log/account/pacct,须要用fread读取acct结构体信息。
  2. 进程调度:进程调整nice值来设置执行优先级(你越nice,你的优先级越低,人艰不拆。。),相关函数:nice/getpriority/setpriority
  3. 进程时间:调用clock_t times(structtms *buf )函数,当中返回值为时钟时间,而tms结构体被下面内容填充:

struct tms {
    clock_t tms_utime; /* user CPU time */
    clock_t tms_stime; /* system CPU time */
    clock_t tms_cutime; /* user CPU time, terminated children */
    clock_t tms_cstime; /* system CPU time, terminated children */
};

注意:相关时间已经通过每秒滴答数(_SC_CLK_TCK)转化成了秒数,但它是从过去任一时间開始统计的,所以其绝对值无意义。一般分别在进程開始和结束调用times,再计算之间的时间差。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119231.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java后台接收参数出现java.lang.Integer cannot be cast to java.lang.Double错误(已解决)[通俗易懂]

    Java后台接收参数出现java.lang.Integer cannot be cast to java.lang.Double错误(已解决)[通俗易懂]在Java接受前端传过来的数据信息的时候,使用List<List<double>>进行接收结果出现这个错误java.lang.Integercannotbecasttojava.lang.Double是类型转换出现的错误,当是这个数据在前端明明处理过,使用parseFloat转为了浮点数后端使用List<List>进行接收,此时也没有报错于是打开debug进行调试检查问题,发现传过来的数值如果是整数则为Integer类型,有小数的才是double类型

    2022年7月16日
    14
  • busybox 安装mysql_busybox 安装问题解决「建议收藏」

    busybox 安装mysql_busybox 安装问题解决「建议收藏」直接编译错误1。loginutils/passwd.c:93:16:error:storagesizeof‘rlimit_fsize’isn’tknown解决方法:在busybox根目录下查找到文件:find-namelibbb.h在libbb.h中添加#include1。MakefileMakefile:431:***mixedimplicitandnormalr…

    2022年7月25日
    13
  • EmWin学习课堂_小白EmWin_EmWin快速入门_EmWin动态内存,显示和触摸屏_EmWin基础配置

    EmWin学习课堂_小白EmWin_EmWin快速入门_EmWin动态内存,显示和触摸屏_EmWin基础配置一、先说说什么是EmWin,它就是一款中间软件包,弄好了之后,我们的界面设计就会变得很简单,在电脑GUI_Builder上做一个界面,生成.c文件,复制到自己的工程里面,我们的显示屏就能得到一模一样的功能。二、在我们使用一个带触摸和显示器的系统的时候,首先就是驱动他们,做完了就应该是这样的:也就是说我们的系统首先得有一个带触摸(不带也行)的系统,接着就是把这两个东西和EmWin关联起来…

    2022年10月14日
    0
  • java中数组的最大下标是_c语言中数组下标从几开始

    java中数组的最大下标是_c语言中数组下标从几开始packagepractice;publicclassExtremeValueAndIndex{ publicstaticvoidmain(String[]args){ intnumberArr[]={7,3,5,1,8,4}; intmax=numberArr[0],min=numberArr[0]; intmaxIndex=0,minIndex=0; for(inti=1;i<numberArr.

    2022年10月11日
    0
  • 开始画PAD图了_ipad如何画图

    开始画PAD图了_ipad如何画图这篇日志本来是应该昨天就写的,但是昨天回去的时候有点累,上了会网,把这个事给忘了。从昨天开始我就要开始画PAD图了,所谓的PAD图就是类似程序流程图的样子,用来帮助程序员快速掌握业务流程的一种方式。组长说先看结算业务主流程,把PAD图画上个两三遍,到下周的时候就要给我分配小任务了,不能再让我像现在这个样子,整天学习一点任务都不做了。尽管听上去不是很爽,但是我内心是十分想做任务的,因为我早就厌烦…

    2022年8月13日
    5
  • Git clone 超级慢

    Git clone 超级慢使用命令:gitclone-br1.13.0https://github.com/tensorflow/models.git克隆GitHub上的一个仓库,但是速度超级慢,最高速度不超过30KB/s解决办法:使用国内镜像网站:github.com.cnpmjs.org,你访问这个网站和访问github.com没有任何区别,但是速度快很多,所以我们可以从这个镜像网站进行克隆仓库。原命令:gitclone-br1.13.0https://github.com/tensorfl

    2022年7月21日
    18

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号