读书笔记-APUE第三版-(8)进程控制
进程ID
每一个进程都有一个唯一的进程ID。几个特殊进程:
- 0号进程是内核进程,一般是调度进程swapper。
- 1号进程init,是用户进程(以root权限执行/sbin/init),负责初始化。
- 几个重要函数: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);
}
- fork函数一次调用,在父进程和自己成中两次返回,由于父进程能够fork多个子进程,所以设计成在父进程中返回子进程pid,而在子进程返回0,由于子进程能够通过getpid和getppid获取自身pid和父进程pid。常见应用场景是在网络编程中,父进程while循环监听用户请求,当接收到用户请求,fork出子进程进行处理。注:linux系统中,fork通过clone系统调用实现。
- waipid函数使用參数0等待指定子进程返回,wait函数家族包含wait(等待任一子进程返回)/waitpid(等待指定子进程&组返回,并能通过第三个參数设置堵塞选项)/waittid(进一步扩展,能获取导致进程终止的信号信息等)/wait3(还能够返回进程使用的资源)/wait4(其它wait函数的入口)。
- exec家族函数的作用是替换掉当前进程上下文(text/data/heap/stack等),运行新的程序(不会创建新进程)。exec家族函数包含execl/execlp/execle/execv/execvp/execve,各个函数主要差别在參数上,当中l表示是列表形式,v表示是指针数组形式,e表示环境变量,p表示命令參数是相对路径,会在PATH路径中搜索。
父子进程
子进程和父进程共享仅仅读的text段,针对bss段、对、栈,现代操作系统使用COW(copy-on-write)技术,仅仅有发生改变时,才会拷贝对应的内存页。
父子进程关系
子进程会继承父进程的大量属性,当中一些重要属性包含:真实/有效用户信息,进程组/会话信息,工作文件夹,环境变量,资源限制等。
父子进程最明显的差别是:子进程的tms时间统计信息被清零,子进程不会继承文件锁,未决闹钟&信号等(兴许章节讨论)。
子进程和父进程返回先后顺序是不确定的,假设用户程序对父子进程运行顺序有依赖,须要自行处理,比方使用信号实现等待通知机制等。
- 内核为每一个正在终止的进程保留了少量信息(pid,终止状态,CPU时间等),便于父进程获取其终止状态。
- 假设子进程在父进程之前结束,而父进程没有wait,子进程会变成僵尸进程。
- 假设父进程先结束,子进程的父进程会变成init进程(pid为1),所以假设要避免僵尸进程的产生,能够两次调用fork,即在子进程中再次调用fork,然后退出。这样第二个fork出来的进程因为其父进程退出,所以被init进程接管。
文件共享
子进程会dup父进程打开的文件描写叙述符(共享文件描写叙述符close-on-exec标记),包含标准输出、输入和错误输出。
如图,父子进程共享file tableentry,位置偏移量一致,所以要父子进程读写同一文件时要注意同步。
设置进程用户ID
之前提到,子进程会继承父进程的uid和euid(有效用户ID),能够调用setuid(setgid)改动进程用户(组)。
- 假设是root用户调用,会同一时候改动进程的uid、euid和备份euid(saved set-user-id)。登陆后,由login(root进程)设置用户ID。
- 非root用户仅仅能改动euid,并且仅仅能改动成之前的uid或者备份euid,否则出错。
- 假设自进程运行exec方法,并且运行程序的set-user-ID位被设置,那么euid被设置被运行程序属主ID。
- 备份euid复制euid。正常情况下,uid=euid=备份euid。
- 程序编写遵循“最小权限“模型,当且仅当程序须要高权限时,才调用setuid提升权限,操作完之后再调用setuid恢复权限。
其它进程相关函数
- 进程审计:acct开启进程审计功能,系统记录已终止进程的统计信息,包含用户ID,启动时间,CPU时间等。Linux系统审计记录保存在/var/log/account/pacct,须要用fread读取acct结构体信息。
- 进程调度:进程调整nice值来设置执行优先级(你越nice,你的优先级越低,人艰不拆。。),相关函数:nice/getpriority/setpriority
- 进程时间:调用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,再计算之间的时间差。
读书笔记-APUE第三版-(8)进程控制的更多相关文章
- 读书笔记-APUE第三版-(7)进程环境
本章关注单进程执行环境:启动&终止.參数传递和内存布局等. 进程启动终止 如图所看到的: 启动:内核通过exec函数执行程序,在main函数执行之前.会调用启动例程(start-up rout ...
- 《Java 8实战》读书笔记系列——第三部分:高效Java 8编程(四):使用新的日期时间API
https://www.lilu.org.cn/https://www.lilu.org.cn/ 第十二章:新的日期时间API 在Java 8之前,我们常用的日期时间API是java.util.Dat ...
- 读书笔记---PMBOK第五版官方中文版
以下是为了准备PMP考试时学习<PMBOK第五版官方中文版>这本书的笔记和摘要,目的是为了以后可以快速的抓住本书的核心重点复习. 引论 PMPOK的目的 收录了项目管理知识体系中被普遍认可 ...
- 《深入理解bootstrap》读书笔记:第三章 CSS布局
一. 概述一下理念 bootstrap基于H5开发.提倡移动先行(媒询声明是必须的),对浏览器支持面不是很广. 响应式图片:max-width:100% height:auto; 可以加上:.img- ...
- Kafka技术内幕 读书笔记之(三) 生产者——消费者:高级API和低级API——基础知识
1. 使用消费组实现消息队列的两种模式 分布式的消息系统Kafka支持多个生产者和多个消费者,生产者可以将消息发布到集群中不同节点的不同分区上:消费者也可以消费集群中多个节点的多个分区上的消息 . 写 ...
- Kafka权威指南 读书笔记之(三)Kafka 生产者一一向 Kafka 写入数据
不管是把 Kafka 作为消息队列.消息总线还是数据存储平台来使用 ,总是需要有一个可以往 Kafka 写入数据的生产者和一个从 Kafka 读取数据的消费者,或者一个兼具两种角色的应用程序. 开发者 ...
- Linux内核分析 读书笔记 (第三章)
第三章 进程管理 3.1 进程 1.进程: 进程就是处于执行期的程序. 进程就是正在执行的程序代码的实时结果. 进程是处于执行期的程序以及相关的资源的总称. 进程包括代码段和其他资源. 2.线程:执行 ...
- webkit技术内幕读书笔记 (二、三)
可视区和网页 通常网页比屏幕的可视区面积要大,因此当网页内容在可视区中放不下时,一般浏览器会提供滚动条. 从URL到构建完DOM树的过程 当用户输入网页URL的时候,WebKit调用其资源加载器加载该 ...
- Linux内核设计与实现 总结笔记(第三章)进程
进程管理 进程:处于执行期的程序. 线程:在进程中活动的对象 虚拟机制 虚拟处理器:多个进程分享一个处理器 虚拟内存:多个线程共享虚拟内存 一.进程描述符和任务结构 进程存放在双向循环链表中(队列), ...
随机推荐
- js对象的属性:数据(data)属性和访问器(accessor)属性
此文为转载,原文: 深入理解对象的数据属性与访问器属性 创建对象的方式有两种:第一种,通过new操作符后面跟Object构造函数,第二种,对象字面量方式.如下 var person = new Obj ...
- JavaScript中构造函数
构造函数:函数的另一种执行方法,执行后创建对象,并创建原型对象. 原型链:对象访问构造函数的指针. Function函数:函数对象. Object函数:所有创建对象的祖辈对象,也是由Function对 ...
- Newtonsoft.Json 序列化器的重写
public class TestConverter : JsonConverter { public override void WriteJson(JsonWriter writer, objec ...
- HA下的Spark集群工作原理解密
实验环境: zookeeper-3.4.6 Spark:1.6.0 简介: 本篇博客将从以下几点组织文章: 一:Spark 构建高可用HA架构 二:动手实战构建高可用HA 三:提交程序测试HA 一:S ...
- Redis数据类型之Set(四)
前言:set类似于数学上面的集合概念,包含的元素无序,不能重复,能进行交.并.差操作. 一.内部原理 set数据结构,也是随着元素数目的多少而变化.当set中添加 ...
- shell实现增加删除Linux系统用户脚本(密码为随机)
README shell环境下运行脚本,根据需求选择相应的功能. List \t\t create the userlist 这一步是必须执行的,脚本会识别本地当前目录下的文件 Useradd \t\ ...
- vim中E121:无法打开并写入文件解决办法
1.使用命令 :w !sudo tee % 保存即可. 其中: 冒号(:)表示我们处于vim的退出模式: 感叹号(!)表示我们正在运行shell命令: sudo和tee都是shell命令: %表示从 ...
- Ionic Js十五:对话框
$ionicPopup ionic 对话框服务允许程序创建.显示弹出窗口. $ionicPopup 提供了3个方法:alert(), prompt(),以及 confirm() . 实例 HTML 代 ...
- 基于 Laravel 开发博客应用系列 —— 设置 Linux/Mac 本地开发环境
1.不同 Linux 发行版本的区别 不同的 Linux 发行版本之间有一些细微区别,尤其是包管理器:CentOS 和 Fedora 使用 yum 作为包管理器,而Ubuntu 使用 apt,在 O ...
- PHP反序列漏洞学习
0x00 序列化和反序列化 在PHP中,序列化和反序列化对应的函数分别为serialize()和unserialize(). 序列化:serialize()将对象转换为字符串以便存储传输的一种方式. ...