Linux 进程与线程(task)

1,031 阅读3分钟

Linux 进程与线程(task)

1. 何为进程和线程?

1.1 二进制程序

  • 二进制程序:指保存在存储介质(磁盘等)上的程序,以给定操作系统(windows、linux等)和计算机体系结构(x86等)可访问的格式(编译生成,比如 windows exe 和 Linux elf 文件格式)。可以运行但尚未开始。

1.2 进程

  • 进程:是操作系统对运行的二进制程序的抽象,包括:加载的二进制程序、虚拟内存、内核资源(如打开的文件列表、关联的用户)等。

1.3 线程

  • 线程:是进程内的执行单元。

2. Linux 如何表示进程与线程?

2.1 在 Linux 中,内核用 task_struct 这一种数据结构代表进程、线程。

Everything is simply a runnable task

Untitled.png

2.2 在 Linux 中,无论是进程还是线程,本质上都是通过 clone 一个已存在 task (进程\线程) 实现的,两者的差别就在于 clone 时 参数的传递。

fork — 进程创建,通过调用 0 共享的 clone 实现

pthread_create — 线程创建,通过调用 最大共享 的 clone实现

2.3 在 Linux 中,top 和 ps 命令对 pid 的理解不一致

ps 文档 (ps 用来查看进程信息(执行命令时进程的快照))

Untitled 1.png

top 文档 (监控各进程占CPU 内存信息)

Untitled 2.png

2.4 常用命令

查看所有进程 ps -aux

查找特定进程 ps -ef | grep "进程相关信息"

例如:获取进程 pid

# 获取PID
PID=$(ps -ef |grep “${JRE_HOME}/bin/java -jar ${APP_HOME}/${APP_NAME}” |grep -v grep |awk '{print $2}')

3. 系统调用 fork() 和 exec()

3.1 进程地址空间

32 bit

Untitled 3.png

section 一般指 elf 文件的分段, segment 指的是 进程地址空间的分段。

3.2 示例

forkProcess.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    pid_t pid;

	// make two process which run same program after this instruction
    // parent process return child process pid
    // child process return 0
	pid = fork();

    if(pid > 0){
        printf("I am the parent of pid = %d \n",pid);
    }else if(!pid){
        printf("I am the child \n");
    }else if(pid == -1){
        perror("fork");
    }
	return 0;
}

运行结果:

Untitled 4.png

fork 产生一个新的子进程,和父进程共享代码段(写时复制—copy on write,提升内存利用率),若子进程需要装载其它的二进制程序,则需用到 exec 函数。

4. linux 一切皆文件,那文件如何将上述概念串联起来?

  • 进程级别文件描述符表。
  • 系统级别打开文件表。
  • 磁盘的 i-node 表,内核一般会存放一个副本在内存中。

Untitled 5.png

参考文献

进程和线程之间有什么根本性的区别?

理解Linux的文件描述符FD与Inode