Linux系统基础——程序和进程
代码,程序,进程
特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料,本文大部分内容和图片来源于这个专栏。
1 实验环境
运行一个demo,主要功能是主进程通过系统调用fork一个新的进程,子进程功能是加载二进制文件,运行ls命令。
1.1 代码: 文本文件
1、 目录结构
[root@VM_16_8_centos test]# tree .
.
|-- createprocess.c
`-- process.c0 directories, 2 files
2、 编辑&编译&运行
// process.c
#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 (); // 1.创建子进程if (child_pid != 0)return child_pid;else {execvp (program, arg_list); //2.子进程通过execvp去运行一个新的程序abort ();}
}
// createprocess.c#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>extern int create_process (char* program, char** arg_list);int main ()
{char* arg_list[] = {"ls","-l","/etc/yum.repos.d/",NULL};create_process ("ls", arg_list); //让子进程执行ls命令return 0;
}
1.2 程序: 二进制文件
#### 第一种方式 ##### 编译成.o文件
gcc -c -fPIC process.c
gcc -c -fPIC createprocess.c
# 生成库文件
ar cr libstaticprocess.a process.o # process.o编译成静态库
# 链接为可执行文件
gcc -o staticcreateprocess createprocess.o -L. -lstaticprocess#### 第二种方式 ##### 编译成.o文件
gcc -c -fPIC process.c
gcc -c -fPIC createprocess.c
# 生成库文件
gcc -shared -fPIC -o libdynamicprocess.so process.o # process.o编译成共享库
# 链接为可执行文件
gcc -o dynamiccreateprocess createprocess.o -L. -ldynamicprocess
1.3 进程: 运行时
#### 第一种方式 ####
$ ./staticcreateprocess
$ total 40
-rw-r--r--. 1 root root 1572 Oct 24 18:38 CentOS-Base.repo
......#### 第二种方式 ####
$ export LD_LIBRARY_PATH=.
$ ./dynamiccreateprocess
$ total 40
-rw-r--r--. 1 root root 1572 Oct 24 18:38 CentOS-Base.repo
......
2 过程分析
2.1 总体框图
代码经过编译和链接生成ELF格式的可执行文件,进程通过exec系列系统调用,将可执行文件加载到内存中执行。
图右边的文件编译过程,生成 so 文件和可执行文件,后面对部分内容整理。
图左边对刚才的代码进行补充:用户态的进程 A 执行 fork,创建进程 B,在进程 B 的处理逻辑中,执行 exec 系列系统调用。这个系统调用会通过 load_elf_binary 方法,将刚才生成的可执行文件,加载到进程 B 的内存中执行。
2.2 编译和链接
1、文本文件转换到二进制文件
编译工具链将我们写好的代码转换成二进制文件,在Linux系统中识别的是elf格式的二进制文件。大致流程为
elf格式有可重定位文件
、可执行文件
、动态链接库
几种类型。
2.3 运行程序为进程
如何将elf格式的二进制程序加载到内存运行的呢?
1、 内核源码
内核中定义加载二进制文件的方法
struct linux_binfmt {struct list_head lh;struct module *module;int (*load_binary)(struct linux_binprm *);int (*load_shlib)(struct file *);int (*core_dump)(struct coredump_params *cprm);unsigned long min_coredump; /* minimal dump size */
} __randomize_layout;
对于 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,
};
对于方法load_elf_binary
,源码中有调用链: do_execve->do_execveat_common->exec_binprm->search_binary_handler。
而do_execve
其实被一组exec的系统调用实现
SYSCALL_DEFINE3(execve,const char __user *, filename,const char __user *const __user *, argv,const char __user *const __user *, envp)
{return do_execve(getname(filename), argv, envp);
}
2、 理解
之前子进程代码中执行了方法exec
,运行一个elf文件。其实通过命令行执行一个程序的时候,也有类似的实现。通过strace
命令查看其中一个命令执行了哪些系统调用
[root@VM_16_8_centos demo]# strace ls
execve("/usr/bin/ls", ["ls"], [/* 28 vars */]) = 0
brk(NULL) = 0xb87000
....
2.4 fork新进程
所有进程都是从父进程fork过来的,那总归有一个祖宗进程,这就是咱们系统启动的init
进程。下面是linux进程树,也可以通过ps -ef
命令查看
2.5 补充知识
1、 了解ELF文件格式
ELF格式有可重定位文件
、可执行文件
、动态链接库
几种类型。
- 第一种是
可重定位文件
,也就是代码编译后生成的.o文件,这类文件还没有被链接,所以相当于一个代码片段。 - 第二种是
可执行文件
,链接后的程序,可直接加载到虚拟内存上运行的一类文件。 - 第三种是
动态链接库
,生成的库文件,动态库能被多个程序共享。程序并没有将动态库的代码包含进去(静态库的方式),相当于仅仅包括对动态链接库的引用。
2、 了解Linux系统中的进程,如查看进程
命令ps -ef
查看Linux系统中的进程
[root@VM_16_8_centos demo]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Mar01 ? 00:05:19 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0 0 Mar01 ? 00:00:00 [kthreadd]
root 3 2 0 Mar01 ? 00:01:40 [ksoftirqd/0]
root 5 2 0 Mar01 ? 00:00:00 [kworker/0:0H]
root 7 2 0 Mar01 ? 00:00:00 [migration/0]
root 8 2 0 Mar01 ? 00:00:00 [rcu_bh]
root 9 2 0 Mar01 ? 00:04:46 [rcu_sched]
root 10 2 0 Mar01 ? 00:00:00 [lru-add-drain]
root 11 2 0 Mar01 ? 00:00:16 [watchdog/0]
root 13 2 0 Mar01 ? 00:00:00 [kdevtmpfs]
....
3、 几种查看文件格式的工具
readelf
工具用于分析 ELF 的信息,objdump
工具用来显示二进制文件的信息,hexdump
工具用来查看文件的十六进制编码,nm
工具用来显示关于指定文件中符号的信息。
9 References
- https://time.geekbang.org/column/article/90855
Linux系统基础——程序和进程相关推荐
- 11、Linux系统基础原理、进程管理工具、任务计划
Linux进程及作业管理 内核的功用:进程管理.文件系统.网络功能.内存管理.驱动程序.安全功能 Process: 运行中的程序的一个副本: 存在生命周期 Linux内核存储进程信息的固定 ...
- 嵌入式Linux系统基础程序开发
文章目录 一. ubuntu开发环境下使用gcc编译c程序 1.编写helloworld的c程序 2.编写一个主程序文件 main1.c 和一个子程序文件 sub1.c 二,在window系统中使用 ...
- Linux系统基础知识
Linux系统基础知识 1.在Linux系统中,以文件方式访问设备. 2. Linux内核引导时,从文件 /etc/fstab中读取要加载的文件系统. 3. Linux文件系统中每个文件用 ino ...
- Linux系统和程序中的DEP和ASLR保护机制
2014年,OpenSSL加密库中的一个缓冲区溢出漏洞被公开.该缺陷被称为"心脏出血".它使受欢迎的在线服务和软件平台的数亿用户暴露于易受攻击的OpenSSL软件版本中.于是操作系 ...
- Linux 系统基础知识
温故而知新,可以为师矣.好久没有再次系统学习 Linux 相关的知识了,总结回顾一下,为了更好的前进. 一.环境搭建 环境的配置,是我们学习的基础.环境配置会用到的工具及环境: (1) Int ...
- linux培训描述,【linux培训班】关于linux系统记录和描述进程的分析
从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?也许我们习惯用Windows系统,可程序员最爱的还是linux系统,毕竟这样的系统安全性比较高,可操作的难度也是有的,不适合小白来使用. ...
- Linux系统状态检测及进程控制--2
Linux系统状态检测及进程控制--1(http://crushlinux.blog.51cto.com/2663646/836481) 4.僵死(进程已终止,但进程描述符存在,直到父进程调用wait ...
- .gpg 进程 linux,小知识之Linux系统中的最大进程数,最大文件描述,最大线程数...
今天来了解一下linux里面的一些小知识: (一)Linux系统中最大可以起多少个进程? (1)32位系统中最多可以起32768个进程 (2)64位系统中最多可以起2的22次方(4194304)约42 ...
- Linux系统编程 74 孤儿进程和僵尸进程
Linux系统编程 74 孤儿进程和僵尸进程 学习笔记 孤儿进程:父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为 init进程,称为init进程领养了孤儿进程. init进程会去接替 ...
最新文章
- asp.net 中显示各类文件
- metasploit 一款开源的渗透测试框架
- VBA在EXCEL中创建图形线条
- jedate-开始使用一款好用的时间插件
- python控制语句中的条件语句_『Python』条件控制语句
- gulp+PC前端静态页面项目开发
- HTML+CSS+JS实现 ❤️CSS3图片遮罩高亮显示❤️
- python判断正负零_【译】格式字符串语法
- Mysql客户端是不是jdbc_关于JDBC连接MySQL的问题,我一直解决不了(Myeclipse 环境下)...
- 【原始图像】对数及对比度扩展变换
- Linux Shell 在运维中的经验总结
- STM32学习——GPIO应用之按键实验
- c语言输入abc求方程的根,编写程序,输入系数abc,计算任意二次方根的实根
- Data Vault初探(十) —— 星型模型向Data Vault模型转化
- 简单实现一个虚拟形象系统
- 聊聊支付通道那些事儿——介绍和接入
- 《AngularJS深度剖析与最佳实践》一2.10 承诺
- 装机必备软件之后端开发篇
- SVG—初识5之SVG变形动画和阶段性学习成果展示
- 3G入门教程--通讯基础