代码,程序,进程

特此说明: 刘超的趣谈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系统基础——程序和进程相关推荐

  1. 11、Linux系统基础原理、进程管理工具、任务计划

    Linux进程及作业管理 ​ 内核的功用:进程管理.文件系统.网络功能.内存管理.驱动程序.安全功能 ​ Process: 运行中的程序的一个副本: ​ 存在生命周期 Linux内核存储进程信息的固定 ...

  2. 嵌入式Linux系统基础程序开发

    文章目录 一.​ ubuntu开发环境下使用gcc编译c程序 1.编写helloworld的c程序 2.编写一个主程序文件 main1.c 和一个子程序文件 sub1.c 二,在window系统中使用 ...

  3. Linux系统基础知识

    Linux系统基础知识 1.在Linux系统中,以文件方式访问设备.   2. Linux内核引导时,从文件 /etc/fstab中读取要加载的文件系统. 3. Linux文件系统中每个文件用 ino ...

  4. Linux系统和程序中的DEP和ASLR保护机制

    2014年,OpenSSL加密库中的一个缓冲区溢出漏洞被公开.该缺陷被称为"心脏出血".它使受欢迎的在线服务和软件平台的数亿用户暴露于易受攻击的OpenSSL软件版本中.于是操作系 ...

  5. Linux 系统基础知识

      温故而知新,可以为师矣.好久没有再次系统学习 Linux 相关的知识了,总结回顾一下,为了更好的前进. 一.环境搭建   环境的配置,是我们学习的基础.环境配置会用到的工具及环境: (1) Int ...

  6. linux培训描述,【linux培训班】关于linux系统记录和描述进程的分析

    从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?也许我们习惯用Windows系统,可程序员最爱的还是linux系统,毕竟这样的系统安全性比较高,可操作的难度也是有的,不适合小白来使用. ...

  7. Linux系统状态检测及进程控制--2

    Linux系统状态检测及进程控制--1(http://crushlinux.blog.51cto.com/2663646/836481) 4.僵死(进程已终止,但进程描述符存在,直到父进程调用wait ...

  8. .gpg 进程 linux,小知识之Linux系统中的最大进程数,最大文件描述,最大线程数...

    今天来了解一下linux里面的一些小知识: (一)Linux系统中最大可以起多少个进程? (1)32位系统中最多可以起32768个进程 (2)64位系统中最多可以起2的22次方(4194304)约42 ...

  9. Linux系统编程 74 孤儿进程和僵尸进程

    Linux系统编程  74 孤儿进程和僵尸进程 学习笔记 孤儿进程:父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为 init进程,称为init进程领养了孤儿进程. init进程会去接替 ...

最新文章

  1. asp.net 中显示各类文件
  2. metasploit 一款开源的渗透测试框架
  3. VBA在EXCEL中创建图形线条
  4. jedate-开始使用一款好用的时间插件
  5. python控制语句中的条件语句_『Python』条件控制语句
  6. gulp+PC前端静态页面项目开发
  7. HTML+CSS+JS实现 ❤️CSS3图片遮罩高亮显示❤️
  8. python判断正负零_【译】格式字符串语法
  9. Mysql客户端是不是jdbc_关于JDBC连接MySQL的问题,我一直解决不了(Myeclipse 环境下)...
  10. 【原始图像】对数及对比度扩展变换
  11. Linux Shell 在运维中的经验总结
  12. STM32学习——GPIO应用之按键实验
  13. c语言输入abc求方程的根,编写程序,输入系数abc,计算任意二次方根的实根
  14. Data Vault初探(十) —— 星型模型向Data Vault模型转化
  15. 简单实现一个虚拟形象系统
  16. 聊聊支付通道那些事儿——介绍和接入
  17. 《AngularJS深度剖析与最佳实践》一2.10 承诺
  18. 装机必备软件之后端开发篇
  19. SVG—初识5之SVG变形动画和阶段性学习成果展示
  20. 3G入门教程--通讯基础

热门文章

  1. @echo与echo区别
  2. kappa系数---学习笔记
  3. 【产品-用户反馈-大众点评】
  4. mklink目录连接
  5. 《机械与电子》期刊简介
  6. I3D网络主体代码详解
  7. 深度学习:Bilinear model
  8. MySQL清空表且id自增长从0开始
  9. unity3D游戏开发实战(五)——声音
  10. 以太网的帧间隙、前导码、帧开始定界符