Linux — 进程管理
进程创建
进程通过fork()创建的大致过程:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
extern int create_process(char* program, char** arg_list);
int create_process(char* program, char** arg_list){
pid_t child_pid;
child_pid = fork();
if(child_pid !=0 ){
return child_pid;
}else{
execvp(program, arg_list);
abort();
}
}
概览图:

编译知识
静态库
这里额外补充一些编译相关的内容。一个源码文件要变成可执行的程序,需要经过编译、链接。

这里编译出的.o文件,就是ELF的第一种类型,可重定位文件,格式如下:

.text:存放编译好的二进制可执行代码.data:已经初始化好的全局变量.rodata:只读数据,例如字符创常量、const常量.bss:未初始化全局变量,运行时会置0.symtab:符号表,记录的是函数和变量.strtab:字符串表、字符串常量和变量名
在程序中我们提到过函数栈,局部变量是放在栈里的,在运行期随时分配、随时释放。这里讨论的是文件,还没到执行阶段。
如要将函数作为库文件被重用,不能以.o的形式存在,而是要形成库文件,最简单的类型是静态链接库.a文件。
ar cr libstaticprocess.a process.o
# 形成二进制执行文件staticcreateprocess
gcc -o staticcreateprocess createprocess.o -L. -lstaticprocess
上述第二条命令链接时,createprocess.o调用了create_process函数,但不知道位置,通过将process.o合并进来,就可以确定位置了。这里形成了ELF的第二种格式:

和.o相似,文件被分为多个section,通过节头表来描述。这里除了段描述之外,最重要的是p_vaddr——加载到内存的虚拟地址。
静态库特点:
一旦链接,代码和变量的section都合并在一起。当程序运行后,就不依赖这个库是否存在
但如果相同的代码段被多个程序使用时,在内存里就存在多份
当静态库更新了,需重新编译二进制执行文件以应用更新
动态库
当动态链接库被链接到一个程序文件时,最后的程序文件并不包括动态链接库中的代码,而仅仅包括对动态链接库的引用,并且不保存动态链接库的全路径,仅保存其名称。
gcc -shared -fPIC -o libdynamicprocess.so process.o
gcc -o dynamiccreateprocess createprocess.o -L. -ldynamicprocess
执行此程序时,先寻找动态链接库,再进行加载。默认,系统在/lib和/usr/lib 路径下寻找,找不到则报错。可以通过设定LD_LIBRARY_PATH环境变量,指定动态链接库的路劲。
动态链接库,就是ELF的第三种类型,共享对象文件。
多个
.interp的Segment,里面是ld-linux.so动态连接器,执行链接动作多个
.plt和.got.plt,分别是 过程链接表(PLT) 和 全局偏移量表(GOT) 。
接下来,我们来看下程序运行时,是如何将so文件动态链接到进程空间的?
dynamiccreateprocess程序调用libdynamicprocess.so里的create_process函数时,是运行时才去找的,编译压根不知道在哪,因此在PLT里建立一个PLT[x]——在二进制程序里,不直接调用函数,而是调用PLT[x]里的代理代码,它会在运行时找到真正的create_process函数。去哪找?去GOT里——它会为
create_process函数创建GOT[y],对应运行时create_process函数在内存中真正的地址。GOT又是咋知道的?对于
create_process函数,GOT在开始时会创建GOT[y],但开始这里没有真正的地址,因为不知道...,它又回调PLT,告诉他:你里面的代理代码来找我要create_process的真实地址,我不知道,你自己想想。PLT只能去调用PLT[0],PLT[0]去调用GOT[2],这里面保存
ld-linux.so入口函数,它去找到加载到内存中的libdynamicprocess.so里的create_process函数地址,然后把这个地址放到GOT[y]中,以供下次PLT[x]调用。
运行程序为进程
ELF二进制文件是如何加载到内存里的?
static struct linux_binfmt elf_format = {
.module = THIS_MODULE,
.load_binary = load_elf_binary,
.load_shlib = load_elf_library,
.core_dump = elf_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE,
};
具体调用链:do_execve->do_execveat_common->exec_binprm->search_binary_handler。
在系统调用时,exec最终调用的是load_elf_binary.

进程树
所有进程的祖宗进程,就是系统启动时的init进程。init进程会启动很多daemon进程,为系统运行提供服务。然后启动getty,让用户登录,登录后运行shell。

1号进程是
/sbin/init,所有用户态进程的祖先2号进程是内核线程
kthreadd,所有内核态的祖先在
ps -ef下,用户态不带中括号,内核态带中括号
Linux — 进程管理的更多相关文章
- Linux进程管理子系统分析【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51298732 Linux进程管理: 进程与程序: 程序:存放在磁盘上的一系列代码 ...
- 12个Linux进程管理命令介绍(转)
12个Linux进程管理命令介绍 [日期:2015-06-02] 来源:Linux中国 作者:Linux [字体:大 中 小] 执行中的程序在称作进程.当程序以可执行文件存放在存储中,并且运行的 ...
- Linux进程管理知识整理
Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...
- Linux性能及调优指南(翻译)之Linux进程管理
本文为IBM RedBook的Linux Performanceand Tuning Guidelines的1.1节的翻译原文地址:http://www.redbooks.ibm.com/redpap ...
- Linux进程管理专题
Linux进程管理 (1)进程的诞生介绍了如何表示进程?进程的生命周期.进程的创建等等? Linux支持多种调度器(deadline/realtime/cfs/idle),其中CFS调度器最常见.Li ...
- [转帖]十二 个经典 Linux 进程管理命令介绍
https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看. 随笔- 109 ...
- Linux进程管理 (1)进程的诞生
专题:Linux进程管理专题 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 L ...
- Linux进程管理 (2)CFS调度器
关键词: 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 Linux进程管理 ( ...
- Linux进程管理 (7)实时调度
关键词:RT.preempt_count.RT patch. 除了CFS调度器之外,还包括重要的实时调度器,有两种RR和FIFO调度策略.本章只是一个简单的介绍. 更详细的介绍参考<Linux进 ...
- Linux进程管理工具
Linux进程管理工具 Htop yum install htop 参考帮助: http://blog.csdn.net/skh2015java/article/details/53173896 Li ...
随机推荐
- 内核模块的makefile规则详解
内核中的Makefile 这里主要对内核源码各子集目录中的Kbulid(内核的编译系统)Makfile进行简单介绍 这部分式内核驱动或设备驱动开发这最长接触到的 Makefile 的语法包括几个方面 ...
- N次剩余小记
前言 上周在 51nod 交了一些3.4级的题目,然后发现没有写过1级题, 就找到了一道 51nod 1014 \(X^2 \bmod P\) 的题目,当然这题虽然是暴力,但也可以用二次剩余做. 我就 ...
- #莫队,根号分治#洛谷 5071 [Ynoi2015] 此时此刻的光辉
题目传送门 分析 约数个数就是 \(\prod{(c+1)}\),但是带 \(log\) 会TLE, 考虑将每个数分成 \(\leq \sqrt[3]{n}\) 和 \(>\sqrt[3]{n} ...
- Git 删除 .gitignore 生成之前上传的文件
清除缓存 git rm -r --cached . git add . 提交记录 git commit -m "chore: 清除缓存." git push
- Websphere更新应用文件
说明: 由于war包中存在安全漏洞或者需要变更里面的某个jar包,此处列举了两种更新方法,不需要重启服务器,只需重启应用. Websphere对部署好的应用更新jar包方法如下: 方式一.手动替换 ...
- 在linux上使用Qt开发动态库项目,怎么只生成一个so文件
背景: 在linux系统上,我们使用 Qt 开发动态库项目时,会默认生成四个文件:x.so .x.so.1 .x.so.1.0.x.so.1.0.0 四个文件,只有一个真实的so库,剩下的三个都是链 ...
- 多线程-多个子线程执行结果插入List集合
业务场景:将多个子线程的执行结果存入List,但是总会出现List集合的长度小于子线程的执行数的情况 1.错误示例(多个线程同时操作同一个List对象,List是线程不安全) package unit ...
- IIS applicationHost.config 查找历史
背景 iis 有时候需要修改配置,一般来说,我们会去修改applicationHost.config配置,当然,很多时候我们都需要去备份一个配置文件,但是可能忘记了,那么是否有补救的方式? 补救方式 ...
- c# vs 中如何修改类模板
背景 在一些应用中,我们需要去修改我们的类模板,作为标记. 步骤 在这个目录下就是我们的模板: C:\Program Files\Microsoft Visual Studio 10.0\Common ...
- Go 单元测试基本介绍
目录 一.单元测试基本介绍 1.1 什么是单元测试? 1.2 如何写好单元测试 1.3 单元测试的优点 1.4 单元测试的设计原则 二.Go语言测试 2.1 Go单元测试概要 2.2 Go单元测试基本 ...