目录
一,进程介绍
二,进程使用
进程查看
通过系统调用获取进程标识符
通过系统调用创建进程 fork
一,进程介绍
进程是正在执行的程序或命令,每个进程都是一个运行的实体或程序的执行实例,有自己的地址空间,并占用一定系统资源;从内核视角来看,是担当分配系统资源(CPU时间、内存)的实体;
- 即在操作系统中,所有可执行的程序或命令都会产生进程(如简单的命令ls、touch等,执行完即结束,如httpd启动后就一直驻留在系统中的常驻内存进程);
- 程序在执行时,执行者的权限和属性均会载入内存,操作系统会对进程分配一个ID,称为进程ID(即PID);
- 进程可以产生新的进程,称此进程为父进程,新进程为子进程,如bash中执行的ls、touch等命令(bash父进程、ls/touch子进程);即子进程是依赖父进程产生的,若无父进程,子进程也就不存在;
进程控制块 PCB
操作系统负责管理所有进程,包括进程的创建和消亡、进程状态的转换,及分配和回收进程所需的资源等;为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块(PCB Process Control Block);
- PBC是进程实体的一部分,是操作系统中最重要的记录性数据结构;
- PBC是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消;
操作系统创建进程时,会额外申请一块内存(即进程控制块),用于存储、管理和控制进程的信息;由操作系统负责管理和维护,进程和进程控制块数量是对应的;Linux系统的PCB/task_struct;
- task_struct(PCB的一种),描述进程的结构体;
- task_struct 是Linux内核的一种数据结构,会被载入到内存并包含进程信息;
- 运行在系统里的进程,都是以task_struct链表形式存在于内核内;对进程的管理,即是对此链表的增删查改;
task_struct 内容
- 标识符,描述进程的唯一标识符,区别其他进程;
- 状态,任务状态、退出代码、退出信息等;
- 优先级,相当于其他进程的优先级;
- 程序计数器,即将被执行下一指令的地址;
- 内存指针,包括程序代码和进程相关数据的指针,及与其他进程共享的内存块指针;
- 上下文数据,进程执行时寄存器中的数据;
- I/O状态信息,包括显式的I/O请求,分配给进程的I/O设备和被进程使用的文件列表;
- 记账信息,可能包括处理器时间总和,使用时钟数总和,时间限制,记账号等;
- 其他信息;
注:管理的本质是先描述在组织;进程 = 程序 + PCB;
二,进程使用
进程查看、系统调用获取标识符及创建子进程;
进程查看
- 进程信息存于 /proc 文件夹,可通过此文件夹查看;
[wz@192 ~]$ ll /proc
total 0
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1
dr-xr-xr-x. 9 root root 0 7月 9 06:35 10
dr-xr-xr-x. 9 root root 0 7月 9 06:35 11
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1180
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1182
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1183
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1187
dr-xr-xr-x. 9 root root 0 7月 9 06:35 1193
dr-xr-xr-x. 9 root root 0 7月 9 06:35 12
...
[wz@192 Desktop]$ ll /proc/59017
total 0
dr-xr-xr-x. 2 wz wz 0 7月 12 09:17 attr
-rw-r--r--. 1 wz wz 0 7月 12 09:17 autogroup
-r--------. 1 wz wz 0 7月 12 09:17 auxv
-r--r--r--. 1 wz wz 0 7月 12 09:17 cgroup
--w-------. 1 wz wz 0 7月 12 09:17 clear_refs
-r--r--r--. 1 wz wz 0 7月 12 06:32 cmdline
-rw-r--r--. 1 wz wz 0 7月 12 09:17 comm
-rw-r--r--. 1 wz wz 0 7月 12 09:17 coredump_filter
-r--r--r--. 1 wz wz 0 7月 12 09:17 cpuset
lrwxrwxrwx. 1 wz wz 0 7月 12 09:17 cwd -> /home/wz/Desktop
-r--------. 1 wz wz 0 7月 12 09:17 environ
lrwxrwxrwx. 1 wz wz 0 7月 12 06:32 exe -> /usr/bin/bash
- 可通过命令top、ps,来查看大多数进程信息;
[wz@192 Desktop]$ ps axj | head -1 && ps axj | grep bash
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 781 765 765 ? -1 S 0 0:17 /bin/bash /usr/sbin/ksmtuned
2107 2244 2244 2244 ? -1 Ss 1000 0:02 /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic"
59010 59017 59017 59017 pts/0 61546 Ss 1000 0:00 bash
59017 61547 61546 59017 pts/0 61546 S+ 1000 0:00 grep --color=auto bash
通过系统调用获取进程标识符
- 进程id为PID;
- 父进程id为PPID;
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
return 0;
}
通过系统调用创建进程 fork
fork() 通过复制正在调用的进程,来创建新进程;新进程将作为子进程,是父进程的完全副本;
- fork有两个返回值,0代表子进程,大于0代表父进程;
- 子进程返回0;
- 父进程返回子进程的ID;
- 子进程有自己唯一进程ID(PID);
- 父子进程代码共享(只读),数据各自私有一份 ,采用写实拷贝;各自独立,互不干扰;
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
printf("hello proc : %d!, ret: %d\n", getpid(), ret);
sleep(1);
return 0;
}
- fork通常使用if进行分流;
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0){
perror("fork");
return 1;
}
else if(ret == 0)
{
printf("I am child : %d!, ret: %d\n", getpid(), ret); //child
}
else
{
printf("I am father : %d!, ret: %d\n", getpid(), ret); //father
}
sleep(1);
return 0;
}