Linux第四章 进程
4.1 前言
本章讨论进程概念、资源、属性。
4.2 内核和进程的关系
当系统启动时,内核代码被加载到内存,初始化之后,启动第一个用户进程,然后内核的代码就等着用户进程来调度了。
4.3 进程是程序的实例
当程序员编写好一个程序,编译之后会生成这个可执行程序,这个程序可以被运行。
运行程序其实是用户进程(Shell进程)指示内核要启动另一个用户进程,内核便为这个新的进程分配资源,并加载该进程的代码和数据。
一个程序可以被运行多次。
4.3 进程资源
4.3.1 PCB
进程运行时,内核为进程每个进程分配一个PCB(进程控制块),描述进程的信息。
PCB在内核中对应的结构体是task_struct。
4.3.2 虚拟地址空间
每个进程都会分配虚拟地址空间,在32位机器上,该地址空间为4G。
更细节的图例
在进程里平时所说的指针变量,保存的就是虚拟地址。当应用程序使用虚拟地址访问内存时,处理器(CPU)会将其转化成物理地址。
这样做的好处在于:
进程隔离,更好的保护系统安全运行
屏蔽物理差异带来的麻烦,方便操作系统和编译器安排进程地址
思考:如果实现一个智能的myfree函数,该函数会自动判断指针是否在堆上还是在栈上,还是在全局变量中。
4.3.3 CPU
CPU的分配是动态的,不是进程一加载就直接分配的,一般来说每个系统都会有许多进程同时在运行,而CPU只有一个(多核CPU可以认为是多个,但是数量远少于进程数量)。那么,进程就需要排队等待,就好像有100个人,在4个卖饭的窗口买饭一样。
内核将进程PCB放入一个队列,总是让CPU服务队列中的第一个进程,服务时间可以是10毫秒,可以是25毫秒,具体多长时间跟具体系统有关系,这个时间有个名字叫做时间片。一旦这个进程服务时间到,这个进程会被丢到队列尾部,进行排队。进程调度。
内核中有一个常量HZ,一般是100,250, 1000
4.4 进程属性和状态
进程有许多的属性和状态,具体可以看task_struct,这里挑一些常见的进行讲解。
4.4.1 PID
进程编号,内核为每个进程分配一个进程编号,这个是进程的身份证,系统保证了不会重复分配。
通过函数getpid或者命令ps可以查看进程的PID。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
4.4.2 PPID
PPID就是父进程ID,在Linux系统中,除了内核启动的第一个进程,其它进程都有父进程。
通过函数getppid或者命令ps可以查看进程的PPID。
4.4.3 账户ID/组ID
账户分实际账户和有效账户两种,如果你使用test账户登陆系统,但是使用sudo运行程序时,实际账户时test,有效账户时root。
通过函数getuid和geteuid获取真实账户id和有效账户id
通过函数getgid和getegid获得真实账户id和有效账户id
通过setuid,setgid,seteuid,setegid,setreuid,setregid等设置进程的有效和真实账户id。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> int main()
{
uid_t uid = getuid();
uid_t euid = geteuid();
printf("uid =%d, euid=%d\n", (int)uid, (int)euid);
}
4.4.4 进程组ID/会话组ID/控制终端
进程组:getpgrp和setpgid
会话组:getsid和setsid
控制终端:
4.4.5 环境变量
保存该进程运行的环境信息。
进程的环境变量保存在全局变量environ中,
也可以通过setenv、getenv、unsetenv进行设置和获取。
4.4.6 进程状态
启动进程时,该进程在RUNNING状态,RUNNING状态的进程有可能时正在被执行,或者在队列中排队。但是如果进程调用阻塞函数,而运行条件不满足时,该进程会进入挂起状态。挂起状态的进程不再分配CPU,除非等到运行条件满足时。会阻塞进程运行的函数有许多,比如getchar是典型的阻塞调用。
阻塞函数列表可以在man 7 signal中,找到关于阻塞函数的列表。
4.4.7 文件描述符
在进程控制块中,有一个数组保存着打开的文件描述符信息。
4.4.8 进程时间
进程有一些字段,用来记录进程的运行时间。
通过times可以获取进程从运行开始时到执行times函数时,所花费的时间。这个在系统性能优化时特别重要。
简单的程序可以从time命令获取进程的运行时间。
Linux时间相关函数可以从man 7 time获取。
4.4.10 当前工作目录和根目录
当前工作目录是相对地址的相对目录,通过getcwd函数可以获取当前目录,也可以通过pwd或者echo $PWD获取。也可以通过chdir来修改当前工作目录。
根目录是绝对地址的相对目录,可以通过chroot来修改根目录。调用chroot需要root权限。
目录相关资料在man 7 path_resolution。
4.5 动态库和静态库
当使用动态库时,系统会检查该动态库是否已经加载,如果已经加载,则直接映射即可,如果没有加载,那么会加载之后再映射。
如果动态库中有全局变量,那么该全局变量对于不同的进程来说,是相互独立和隔离的。
链接静态库时,静态库被一起编译进可执行程序,运行时不再依赖静态库。
动态库编译:gcc -fpic -shared a.c b.c -o libtest.so
链接动态库gcc main.c -ltest -L. -o mybin
运行程序时
静态库打包:ar rcs libtest.a a.o b.o
链接库时,如果有同名的动态库和静态库,默认优先动态库,如果要链接静态库,那么使用-static,比如
通过以下方式可以指定某些库使用静态链接,而某些库使用动态链接
4.6 内存管理
进程运行时,总是占用内存,无论是加载代码,还是在函数中定义局部变量,还是调用malloc申请内存。
无论是那种原因,进程需要使用内存时,它将向系统申请,并获得相对应的虚拟地址,而进程只能访问虚拟地址,真实的内存地址,进程无法访问。当进程访问虚拟地址时,系统会负责进行虚拟地址到物理地址的转换,系统发现进程尝试访问非法地址,那么进程将得到惩罚(段错误)。
这样做保护了系统的稳定性,不会因为个别新手程序员导致整个系统的崩溃。
另外还有一个好处是,使用虚拟内存之后,每个进程的导致空间是一致的,简化了进程的设计。
相关函数:malloc,brk,mmap,alloca
4.7 进程总结
从用户的角度看,一个程序跑起来就是进程。而从操作系统的角度看,进程是一个控制块+代码+数据的组合。
4.8 函数和命令
4.8.1 函数
getpid:获取进程ID
getppid:获取父进程ID
getuid:获取实际用户ID
getgid:获取实际组ID
geteuid:获取有效账户ID
getegid:获取有效组ID
进程组描述了一项任务
getpgrp:获取进程组号
setpgid:设置进程组号
setsid:设置Session号
getsid:获得Session号
getcwd:获取当前工作目录
chdir:设置当前工作目录
chroot:修改当前根目录
getenv:环境中取字符串,获取环境变量的值
setenv:改变或增加环境变量
unsetenv
extern char** environ(全局变量)
malloc/free:堆区申请内存
mmap/munmap:在映射区申请内存
brk:全局区申请内存
alloca:在栈上申请内存
4.8.2 命令
ps axu:现行终端机下的所有程序,以用户为主的格式来显示程序状况,显示所有程序,不以终端机来区分
ps ajx
grep:搜索
kill:杀死进程(给进程发送信号)
Linux第四章 进程的更多相关文章
- linux第四章笔记
第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间.进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统. 最大限度利用处理器时间的原则:只要有可以执行 ...
- linux第四章读书笔记
第四章 进程调度 一.多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于可运行状态.多 ...
- 2013337朱荟潼 Linux第四章读书笔记——进程调度
第4章 进程调度 0. 总结 调度:调度是一个平衡的过程.一方面,它要保证各个运行的进程能够最大限度的使用CP:另一方面,保证各个进程能公平的使用CPU. 调度功能:决定哪个进程运行以及进程运行多长时 ...
- Windows核心编程 第四章 进程(下)
4.3 终止进程的运行 若要终止进程的运行,可以使用下面四种方法: • 主线程的进入点函数返回(最好使用这个方法) . • 进程中的一个线程调用E x i t P r o c e s s函数(应该避免 ...
- windows核心编程---第四章 进程
上一章介绍了内核对象,这一节开始就要不断接触各种内核对象了.首先要给大家介绍的是进程内核对象.进程大家都不陌生,它是资源和分配的基本单位,而进程内核对象就是与进程相关联的一个数据结构.操作系统内核通过 ...
- 20135320赵瀚青LINUX第四章读书笔记
概述 什么是进程调度 进程调度:在可运行态进程之间分配有限处理器时间资源的内核子系统. 一.调度策略 4.1进程类型 I/O消耗型进程:大部分时间用来提交I/O请求或是等待I/O请求,经常处于可运行状 ...
- Windows核心编程 第四章 进程(中)
4.2 CreateProcess函数 可以用C r e a t e P r o c e s s函数创建一个进程: BOOL CreateProcessW( _In_opt_ LPCWSTR lpAp ...
- Windows核心编程 第四章 进程(上)
第4章 进 程 本章介绍系统如何管理所有正在运行的应用程序.首先讲述什么是进程,以及系统如何创建进程内核对象,以便管理每个进程.然后将说明如何使用相关的内核对象来对进程进行操作.接着,要介绍进 ...
- 《Linux内核设计与实现》读书笔记 第四章 进程调度
第四章进程调度 进程调度程序可看做在可运行太进程之间分配有限的处理器时间资源的内核子系统.调度程序是多任务操作系统的基础.通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发执行的 ...
随机推荐
- 从缓存入门到并发编程三要素详解 Java中 volatile 、final 等关键字解析案例
引入高速缓存概念 在计算机在执行程序时,以指令为单位来执行,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入. 由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这 ...
- Django 之ModelAdmin对象
一.后台管理系统配置 1 在该表对应的models类里面添加一个Meta类 class Meta: verbose_name_plural = '用户表' #指定该表在admin后台的名字为:用户表 ...
- proxy解决跨域问题
首先我们在本地开发,域名都是localhost,当我们需要请求后台数据时,就会出现跨域的问题 下面就是在vue.config.js配置文件里: devServer: { proxy: { ...
- 为Azure-云准备一个基于Red Hat 8.x 的虚拟机镜像
由于公司最近要求部分项目上线到Azure云上,要求操作系统使用的Redhat 8.x,而且必须加固 而在Azure官网提供的镜像中,又没有Redhat,于是只有自己自定义Redhat镜像,最后加固,作 ...
- 面向对象的照妖镜——UML类图绘制指南
1.前言 感受 在刚接触软件开发工作的时候,每次接到新需求,在分析需求后的第一件事情,就是火急火燎的打开数据库(DBMS),开始进行数据表的创建工作.然而这种方式,总是会让我在编码过程中出现实体类设计 ...
- Filter 筛选器(一)之 ActionFilter-- IAsyncActionFilter 和 ActionFilterAttribute
微软官网例子:Filter筛选器 使用场景(执行顺序): IAsyncActionFilter 使用异步actionFilter 只需要实现 他的 :OnActionExecutionAsync 方法 ...
- VP记录
预计在最后的日子里适量VP 简单记录一下 CF 1037 Link 上来秒了ABCD,很快啊 A是二进制拆分,B是一眼贪心,C是一个非常简单且好写的dp D把边遍历顺序按照所需的bfs顺序排序,最后比 ...
- 优雅的重启uwsgi 告别uwsgi reload过程中造成的无法请求、请求延迟等问题
[uwsgi]#使用优雅重启 lazy-apps = true #监听monitor文件 当monitor文件发生改变是重启uwsgi touch-chain-reload = /home/monit ...
- i春秋时间
打开题目就是一段php代码 大致的意思是 ------------------------------------------------------------------------------- ...
- ubuntu 18.04安装tensorflow (CPU)
在已经安装anaconda环境及pip之后. 添加并设置pip配置文件: mkdir ~/.pip vim ~/.pip/pip.conf pip.conf文件内容: [global] index-u ...