进程和程序
进程时程序的实体化,程序被储存在磁盘当中,当程序被加载到内存当中(执行起来),操作系统利用PCB将进程描述起来,Linux下PCB是:task_struct
task_struct是一种数据结构,用来描述进程,包含进程的各种信息,包括进程号PID 状态 优先级等等很多信息
9 task_struct包含的信息:
10 标识符 : pid
11 状态 : 就绪,运行,睡眠,阻塞等等
12 I/O状态信息: 进程打开的文件的信息
13 记账信息 :进程运行时间等
14 内存指针 : 包括程序代码和进程相关数据的指针,还有其他进程共享的内存块的指针
15 程序计数器 : 程序中即将被执行的下一条指令(当兵例子)
16 上下文数据 : 进程执行时处理器中寄存器的数据
17 优先级 :决定进程被调度的优先级
18 等
查看进程
查看进程可以通过/proc系统文件夹来查看
[liu@localhost 进程]$ ls /proc/
1 1959 2463 29 335 5 67 83 diskstats mdstat sysrq-trigger
10 1993 2475 3 34 50 68 84 dma meminfo sysvipc
11 2 2476 30 35 51 681 9 driver misc timer_list
1151 20 2477 3017 36 52 69 91 execdomains modules timer_stats
1152 2027 25 3021 37 53 7 92 fb mounts tty
12 2045 2504 3022 38 535 70 93 filesystems mpt uptime
1201 2059 2519 3091 39 54 71 94 fs mtd version
13 2065 2540 31 4 55 72 95 interrupts mtrr vmallocinfo
131 2084 2542 3161 40 56 73 97 iomem net vmstat
132 2090 2544 3198 41 57 74 98 ioports pagetypeinfo zoneinfo
14 21 2546 3199 42 58 75 99 irq partitions
15 2122 2548 32 429 59 76 acpi kallsyms sched_debug
1551 2134 2550 320 43 6 77 asound kcore schedstat
1574 2135 2557 3203 430 60 78 buddyinfo keys scsi
16 2179 2558 3204 44 61 79 bus key-users self
1607 2187 2565 321 45 62 8 cgroups kmsg slabinfo
165 22 26 3228 46 63 80 cmdline kpagecount softirqs
17 23 2632 33 47 64 81 cpuinfo kpageflags stat
18 2332 27 333 48 65 82 crypto loadavg swaps
19 24 28 334 49 66 820 devices locks sys
查看进程也可以用ps aux 或者 ps -ef
[liu@localhost 进程]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 2900 1436 ? Ss 07:17 0:01 /sbin/init
root 2 0.0 0.0 0 0 ? S 07:17 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 07:17 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S 07:17 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S 07:17 0:00 [stopper/0]
root 6 0.0 0.0 0 0 ? S 07:17 0:00 [watchdog/0]
[liu@localhost 进程]$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:17 ? 00:00:01 /sbin/init
root 2 0 0 07:17 ? 00:00:00 [kthreadd]
root 3 2 0 07:17 ? 00:00:00 [migration/0]
root 4 2 0 07:17 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 07:17 ? 00:00:00 [stopper/0]
root 6 2 0 07:17 ? 00:00:00 [watchdog/0]
root 7 2 0 07:17 ? 00:00:00 [migration/1]
系统调用创建进程fork
形式 : pid_t fork(void);
fork()会创建一个子进程,拥有和父进程相同的资源,包括代码数据等等, 看看man手册对于fork的描述
NAME
fork - create a child process
SYNOPSIS
#include <unistd.h>
pid_t fork(void);
DESCRIPTION
fork() creates a new process by duplicating(复制) the calling process. The new
process, referred to as the child, is an exact duplicate of the calling pro-
cess, referred to as the parent
子进程与父进程的调用顺序完全随机,由cup和就绪队列的状态所决定
fork创建子进程成功会产生对两个进程产生不同的返回值,对于子进程是返回0,父进程是返回子进程的PID,若是创建进程失败,则返回-1
fork用法举例 :
getpid()可以获得当前进程的pid
3 #include <stdio.h>
4 #include <unistd.h>
5
6
7 int main(void)
8 {
9 pid_t id = fork();
10 if(id < 0){
11 printf("failed \n ");
12 return -1;
13 }else if(id == 0){
14 printf("this is child : %d !!! \n", getpid());
15 }else{
16 printf("this is parent : %d !!! \n", getpid());
17 }
18
19 printf("this is comman : %d !!!\n", getpid());
20
21 return 0;
22 }
运行结果 :
[liu@localhost day01]$ make
cc fork.c -o fork
[liu@localhost day01]$ ./fork
this is parent : 3322 !!!
this is comman : 3322 !!!
this is child : 3323 !!!
this is comman : 3323 !!!
进程状态
进程状态在kernel源码中的定义 :
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"Z (zombie)", /* 16 */
"X (dead)", /* 32 */
};
- R (Runing)运行状态 : 并不意味着进程一定在运行中,它表明进程要么在运行状态中,要么正在运行队列里
- S((interruptible)Sleeping)(可中断)睡眠状态:意味着进程在等待着事情的完成
- D(Disk Sleeping)磁盘休眠状态(不可中断睡眠状态):在这个状态的进程通常会等待IO的结束
- T(Stopped)停止状态:可以发送SIGTOP信号来给进程停止,暂时被停止的进程可以通过发送SIGCONT信号让进程继续运行
- X(Dead)死亡状态 : 这个状态是一个返回状态,不能再任务列表看到这个状态
- Z(Zombie)僵尸状态:正常退出失败,即死亡还拥有资源,造成的危害进程状态
系统进程状态的修改
僵尸进程状态分析
- 当前进程退出并且父进程未处理子进程的退出信息或者未接收到退出信息,这时就会产生僵尸进程
- 僵尸进程会以终止状态保持在进程表里,并且一直等待父进程读取退出状态码
创建一个维持十秒的僵尸进程的例子
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 int main(void)
6 {
7 pid_t id = fork();
8 if(id < 0){
9 printf("error\n");
10 return -1;
11 }
12 else if(id == 0)
13 {
14 printf("this is child process\n");
15 sleep(1);
16 exit(0);
17 }
18 else{
19 sleep(20);
20 }
21 return 0;
22 }
监视结果,出现Z(僵尸)状态
[liu@bogon day01]$ ps aux | grep js
liu 3750 0.0 0.0 1864 316 pts/1 S+ 09:14 0:00 ./js
liu 3751 0.0 0.0 0 0 pts/1 Z+ 09:14 0:00 [js] <defunct>
liu 3755 0.0 0.0 4420 772 pts/0 S+ 09:15 0:00 grep js
僵尸进程的危害
- 进程退出状态也需要PCB来维护其数据,若保存Z状态不退出,则会一直要维护PCB造成内存泄漏