Linux:进程的本质和fork初识

简介: Linux:进程的本质和fork初识

回顾进程

前面对进程进行了一些初步的认知,比如进程=可执行程序+内核数据结构PCB,再比如可以通过ps命令搭配管道寻找进程,通过/proc系统文件夹查看进程的信息,这些都是前面对进程建立起来的一些初步的认知

查看进程的方式

下面引入在函数中使用进程的函数,getpid()gitppid

#include <stdio.h>
#include <unistd.h>
int main()
{
    while(1)
    {
        printf("process id:%d,parent process id:%d\n",getpid(),getppid());
        sleep(1);
    }
    return 0;
}

这两个函数的功能,就是得到进程的id和父进程的id

实现Makefile

cc=gcc
src=process.c
target=process 
$(target):$(src)
  gcc -o $@ $^
.PHONY:clean
clean:
  rm -f $(target)

在启动程序前,为了便于观察进程的变化情况,我们可以借助ps命令来观察,但是ps命令不能做到实时观察目前我们的进程变换情况,因此使用一个脚本来自动的观察进程的情况

# 打印ps指令的题头和利用ps指令寻找关于process的进程信息,打印一次暂停1s,再使用####进行分割每次打印的信息
while :; do ps ajx |head -1 && ps ajx | grep process; sleep 1;echo "###################################"; done

执行程序和脚本

下面对这个程序进行多次执行

# 第一次可执行程序运行的结果
process id:11389,parent process id:7945
# 进程监视的结果
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 7945 11389 11389  7945 pts/0    11389 S+    1003   0:00 ./process
# 第二次可执行程序运行的结果
process id:14823,parent process id:7945
# 进程监视的结果
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 7945 14823 14823  7945 pts/0    14823 S+    1003   0:00 ./process
# 第三次可执行程序运行的结果
process id:15279,parent process id:7945
# 进程监视的结果
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 7945 15279 15279  7945 pts/0    15279 S+    1003   0:00 ./process

输出结果如上,从中可以看出这个函数是可以打印出进程的信息的,和实际的信息也确实对应,但是有一个现象,父进程一直都是7945,为什么不变呢?

理解系统接口调用

从这里其实可以更深层次的理解下图中关于系统调用接口的概念,我们使用的不管是getpid还是getppid,实际上都是要调用系统的接口,操作系统再帮我们进行一个搜索后把结果返还给用户,逻辑上是很简单的一个过程

那么现在有了函数的调用,用户也可以直接去得到进程的id信息,下面进行第二种查看进程的方式,使用/proc文件来查看

proc文件夹,是一个动态的目录结构,里面存放的是所有存在的进程,而目录的名称就是以这个进程的id来命名的

下面展示了/proc文件夹下的各种进程内容,每一个文件夹其实都对应了一个进程,每一个进程文件夹下的内容其实就是每个进程的PCB,那么下面就要进入进程内,看这些进程内到底包含什么东西

[test@VM-16-11-centos process]$ ls /proc -l
total 0
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 10
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1005
dr-xr-xr-x  9 test           test                         0 Sep 23 19:42 10082
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 106
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1070
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1072
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1075
dr-xr-xr-x  9 root           root                         0 Sep 23 19:45 10935
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 11
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1180
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 1188
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1195
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 12
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 1205
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 1206
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 13
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1318
dr-xr-xr-x  9 postfix        postfix                      0 Jul 15 22:07 1328
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 1370
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 14
dr-xr-xr-x  9 postfix        postfix                      0 Sep 23 19:55 14576
dr-xr-xr-x  9 root           root                         0 Sep 11 17:53 14808
dr-xr-xr-x  9 root           root                         0 Sep 11 17:53 14911
dr-xr-xr-x  9 root           root                         0 Aug 30 10:08 15264
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 1565
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 16
dr-xr-xr-x  9 root           root                         0 Sep 23 20:03 17216
dr-xr-xr-x  9 root           root                         0 Sep 23 20:05 17758
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 18
dr-xr-xr-x  9 ntp            ntp                          0 Jul 15 22:07 1800
dr-xr-xr-x  9 test           test                         0 Sep 23 20:09 18814
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 19
dr-xr-xr-x  9 root           root                         0 Sep 23 20:10 19001
dr-xr-xr-x  9 root           root                         0 Sep 23 20:12 19441
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 2
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 20
dr-xr-xr-x  9 root           root                         0 Aug 31 20:02 20043
dr-xr-xr-x  9 root           root                         0 Aug 31 20:02 20051
dr-xr-xr-x  9 root           root                         0 Aug 31 20:02 20052
dr-xr-xr-x  9 root           root                         0 Sep 23 20:15 20184
dr-xr-xr-x  9 test           test                         0 Sep 23 20:15 20221
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 203
dr-xr-xr-x  9 test           test                         0 Sep 12 12:11 20530
dr-xr-xr-x  9 test           test                         0 Sep 12 12:11 20543
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 21
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 22
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 23
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 24
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 25
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 253
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 26
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 262
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 267
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 268
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 269
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 27
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 272
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 277
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 28
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 29
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 292
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 293
dr-xr-xr-x  9 root           root                         0 Sep 22 18:22 29767
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 300
dr-xr-xr-x  9 root           root                         0 Sep 23 19:15 3061
dr-xr-xr-x  9 root           root                         0 Sep 21 20:36 3243
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 35
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 36
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 37
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 38
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 381
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 4
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 404
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 409
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 46
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 48
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 49
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 501
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 51
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 515
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 52
dr-xr-xr-x  9 root           root                         0 Jul 15 22:16 5449
dr-xr-xr-x  9 libstoragemgmt libstoragemgmt               0 Jul 15 22:07 556
dr-xr-xr-x  9 dbus           dbus                         0 Jul 15 22:07 561
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 566
dr-xr-xr-x  9 root           root                         0 Jul 15 22:07 567
dr-xr-xr-x  9 polkitd        polkitd                      0 Jul 15 22:07 568
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 6
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 612
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 613
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 614
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 615
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 616
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 621
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 65
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 7
dr-xr-xr-x  9 root           root                         0 Sep 23 19:34 7937
dr-xr-xr-x  9 test           test                         0 Sep 23 19:34 7944
dr-xr-xr-x  9 test           test                         0 Sep 23 19:34 7945
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 8
dr-xr-xr-x  9 root           root                         0 Sep 11 17:49 9
dr-xr-xr-x  2 root           root                         0 Sep 23 20:15 acpi
-r--r--r--  1 root           root                         0 Sep 23 20:15 buddyinfo
dr-xr-xr-x  4 root           root                         0 Sep 23 20:15 bus
-r--r--r--  1 root           root                         0 Sep 23 20:15 cgroups
-r--r--r--  1 root           root                         0 Sep 23 20:15 cmdline
-r--r--r--  1 root           root                         0 Sep 23 20:15 consoles
-r--r--r--  1 root           root                         0 Sep 23 20:15 cpuinfo
-r--r--r--  1 root           root                         0 Sep 23 20:15 crypto
-r--r--r--  1 root           root                         0 Sep 23 20:15 devices
-r--r--r--  1 root           root                         0 Sep 23 20:15 diskstats
-r--r--r--  1 root           root                         0 Sep 23 20:15 dma
dr-xr-xr-x  3 root           root                         0 Sep 23 20:15 driver
-r--r--r--  1 root           root                         0 Sep 23 20:15 execdomains
-r--r--r--  1 root           root                         0 Sep 23 20:15 fb
-r--r--r--  1 root           root                         0 Sep 23 20:15 filesystems
dr-xr-xr-x  5 root           root                         0 Sep 23 20:15 fs
-r--r--r--  1 root           root                         0 Sep 23 20:15 interrupts
-r--r--r--  1 root           root                         0 Sep 23 20:15 iomem
-r--r--r--  1 root           root                         0 Sep 23 20:15 ioports
dr-xr-xr-x 25 root           root                         0 Sep 23 20:15 irq
-r--r--r--  1 root           root                         0 Sep 23 20:15 kallsyms
-r--------  1 root           root           140737486266368 Sep 23 20:15 kcore
-r--r--r--  1 root           root                         0 Sep 23 20:15 keys
-r--r--r--  1 root           root                         0 Sep 23 20:15 key-users
-r--------  1 root           root                         0 Sep 23 20:15 kmsg
-r--------  1 root           root                         0 Sep 23 20:15 kpagecount
-r--------  1 root           root                         0 Sep 23 20:15 kpageflags
-r--r--r--  1 root           root                         0 Sep 23 20:15 loadavg
-r--r--r--  1 root           root                         0 Sep 23 20:15 locks
-r--r--r--  1 root           root                         0 Sep 23 20:15 mdstat
-r--r--r--  1 root           root                         0 Sep 23 20:15 meminfo
-r--r--r--  1 root           root                         0 Sep 23 20:15 misc
-r--r--r--  1 root           root                         0 Sep 23 20:15 modules
lrwxrwxrwx  1 root           root                        11 Sep 23 20:15 mounts -> self/mounts
-rw-r--r--  1 root           root                         0 Sep 23 20:15 mtrr
lrwxrwxrwx  1 root           root                         8 Sep 23 20:15 net -> self/net
-r--------  1 root           root                         0 Sep 23 20:15 pagetypeinfo
-r--r--r--  1 root           root                         0 Sep 23 20:15 partitions
-r--r--r--  1 root           root                         0 Sep 23 20:15 sched_debug
-r--r--r--  1 root           root                         0 Sep 23 20:15 schedstat
dr-xr-xr-x  3 root           root                         0 Sep 23 20:15 scsi
lrwxrwxrwx  1 root           root                         0 Jul 15 22:07 self -> 20221
-r--------  1 root           root                         0 Sep 23 20:15 slabinfo
-r--r--r--  1 root           root                         0 Sep 23 20:15 softirqs
-r--r--r--  1 root           root                         0 Sep 23 20:15 stat
-r--r--r--  1 root           root                         0 Jul 15 22:07 swaps
dr-xr-xr-x  1 root           root                         0 Jul 15 22:07 sys
--w-------  1 root           root                         0 Sep 23 20:15 sysrq-trigger
dr-xr-xr-x  2 root           root                         0 Sep 23 20:15 sysvipc
-r--r--r--  1 root           root                         0 Sep 23 20:15 timer_list
-rw-r--r--  1 root           root                         0 Sep 23 20:15 timer_stats
dr-xr-xr-x  4 root           root                         0 Sep 23 20:15 tty
-r--r--r--  1 root           root                         0 Sep 23 20:15 uptime
-r--r--r--  1 root           root                         0 Sep 23 20:15 version
-r--------  1 root           root                         0 Sep 23 20:15 vmallocinfo
-r--r--r--  1 root           root                         0 Sep 23 20:15 vmstat
dr-xr-xr-x  2 root           root                         0 Sep 23 20:15 xpmem
-r--r--r--  1 root           root                         0 Sep 23 20:15 zoneinfo

对于产生的结果过多,不太好观察,因此这里将前面的程序启动,看进程中到底有什么文件和信息可以进行获取

# 启动程序
process id:18814,parent process id:7945
# 查看进程内容
[test@VM-16-11-centos process]$ ls /proc/18814 -l
total 0
dr-xr-xr-x 2 test test 0 Sep 23 20:10 attr
-rw-r--r-- 1 test test 0 Sep 23 20:10 autogroup
-r-------- 1 test test 0 Sep 23 20:10 auxv
-r--r--r-- 1 test test 0 Sep 23 20:10 cgroup
--w------- 1 test test 0 Sep 23 20:10 clear_refs
-r--r--r-- 1 test test 0 Sep 23 20:09 cmdline
-rw-r--r-- 1 test test 0 Sep 23 20:10 comm
-rw-r--r-- 1 test test 0 Sep 23 20:10 coredump_filter
-r--r--r-- 1 test test 0 Sep 23 20:10 cpuset
lrwxrwxrwx 1 test test 0 Sep 23 20:09 cwd -> /home/test/process
-r-------- 1 test test 0 Sep 23 20:09 environ
lrwxrwxrwx 1 test test 0 Sep 23 20:09 exe -> /home/test/process/process
dr-x------ 2 test test 0 Sep 23 20:09 fd
dr-x------ 2 test test 0 Sep 23 20:10 fdinfo
-rw-r--r-- 1 test test 0 Sep 23 20:10 gid_map
-r-------- 1 test test 0 Sep 23 20:10 io
-r--r--r-- 1 test test 0 Sep 23 20:10 limits
-rw-r--r-- 1 test test 0 Sep 23 20:10 loginuid
dr-x------ 2 test test 0 Sep 23 20:10 map_files
-r--r--r-- 1 test test 0 Sep 23 20:10 maps
-rw------- 1 test test 0 Sep 23 20:10 mem
-r--r--r-- 1 test test 0 Sep 23 20:10 mountinfo
-r--r--r-- 1 test test 0 Sep 23 20:10 mounts
-r-------- 1 test test 0 Sep 23 20:10 mountstats
dr-xr-xr-x 5 test test 0 Sep 23 20:10 net
dr-x--x--x 2 test test 0 Sep 23 20:10 ns
-r--r--r-- 1 test test 0 Sep 23 20:10 numa_maps
-rw-r--r-- 1 test test 0 Sep 23 20:10 oom_adj
-r--r--r-- 1 test test 0 Sep 23 20:10 oom_score
-rw-r--r-- 1 test test 0 Sep 23 20:10 oom_score_adj
-r--r--r-- 1 test test 0 Sep 23 20:10 pagemap
-r-------- 1 test test 0 Sep 23 20:10 patch_state
-r--r--r-- 1 test test 0 Sep 23 20:10 personality
-rw-r--r-- 1 test test 0 Sep 23 20:10 projid_map
lrwxrwxrwx 1 test test 0 Sep 23 20:09 root -> /
-rw-r--r-- 1 test test 0 Sep 23 20:10 sched
-r--r--r-- 1 test test 0 Sep 23 20:10 schedstat
-r--r--r-- 1 test test 0 Sep 23 20:10 sessionid
-rw-r--r-- 1 test test 0 Sep 23 20:10 setgroups
-r--r--r-- 1 test test 0 Sep 23 20:10 smaps
-r--r--r-- 1 test test 0 Sep 23 20:10 stack
-r--r--r-- 1 test test 0 Sep 23 20:09 stat
-r--r--r-- 1 test test 0 Sep 23 20:10 statm
-r--r--r-- 1 test test 0 Sep 23 20:09 status
-r--r--r-- 1 test test 0 Sep 23 20:10 syscall
dr-xr-xr-x 3 test test 0 Sep 23 20:10 task
-r--r--r-- 1 test test 0 Sep 23 20:10 timers
-rw-r--r-- 1 test test 0 Sep 23 20:10 uid_map
-r--r--r-- 1 test test 0 Sep 23 20:10 wchan

上面演示了查看进程中文件的信息的方法,针对上面的信息,选两个来进行总结

lrwxrwxrwx 1 test test 0 Sep 23 20:09 cwd -> /home/test/process
lrwxrwxrwx 1 test test 0 Sep 23 20:09 exe -> /home/test/process/process

这里挑选出了两个内容,一个是cwd,一个是exe,选这两个也是有原因的,这两个可以挖掘出可值得学习的点

  1. cwd

在解决问题前要先知道什么是cwd,它的全程叫做current working directory,也就是所谓的当前工作目录,一般叫它叫当前目录,对于当前目录这个概念并不陌生,但什么是当前目录?

前面对于进程的定义中讲到,操作系统会创建出一个PCB来管理进入内存中的可执行程序,那么可执行程序是如何被管理的?该如何理解管理的概念?一个进程,要能找到自己的可执行程序,这样才能被称为管理起来,因此,这就意味着每一个进程都要有自己的工作目录,而默认情况下,进程启动的时候所处的路径就是当前路径

既然这是默认,那么当前路径也是可以更改的,有一个函数叫做chdir()函数,它的功能就是用以更变工作路径的,在Linux下使用man指令查看:

SYNOPSIS
       #include <unistd.h>
       int chdir(const char *path);
       int fchdir(int fd);

因此用实验来证明它的存在

对程序略做修改,让程序可以在工作目录下创建文件,可以使用C语言的文件操作来实现

#include <stdio.h>
#include <unistd.h>
int main()
{
    FILE* pf=fopen("test.txt","w");
    if(pf==NULL)
    {
        perror("fopen fail!\n");
        return 1;
    }
    fclose(pf);
    return 0;
}

编译运行结果,此时在process路径下就产生了一个test.txt文件,这也说明默认的工作路径就是进程启动的时候所处的环境,此时再看proc文件下的信息

[test@VM-16-11-centos process]$ ls /proc/3466 -l
total 0
lrwxrwxrwx 1 test test 0 Sep 23 21:17 cwd -> /home/test
lrwxrwxrwx 1 test test 0 Sep 23 21:17 exe -> /home/test/process/process

此时确实是被改变了,说明和前面是一样的

[test@VM-16-11-centos process]$ make
gcc -o process process.c
[test@VM-16-11-centos process]$ ./process
[test@VM-16-11-centos process]$ ll
total 20
-rw-rw-r-- 1 test test  106 Sep 23 19:39 Makefile
-rwxrwxr-x 1 test test 8464 Sep 23 20:47 process
-rw-rw-r-- 1 test test  203 Sep 23 20:45 process.c
-rw-rw-r-- 1 test test    0 Sep 23 20:47 test.txt

那么对于程序再略做修改

#include <stdio.h>
#include <unistd.h>
int main()
{
    chdir("/home/test");
    FILE* pf=fopen("test.txt","w");
    if(pf==NULL)
    {
        perror("fopen fail!\n");
        return 1;
    }
    fclose(pf);
    return 0;
}

此时将工作目录改到了家目录的一个文件夹下,此时再看test.txt的位置

[test@VM-16-11-centos ~]$ pwd
/home/test
[test@VM-16-11-centos ~]$ ll
-rw-rw-r--  1 test test    0 Sep 23 20:50 test.txt

此时程序生成的文件就默认创建到了这个文件夹内,此时打开/proc文件,再看进程的描述

  1. exe

exe表示的就是当前正在执行的可执行程序,如果把可执行程序从磁盘中删除

[test@VM-16-11-centos process]$ ll
total 20
-rw-rw-r-- 1 test test  106 Sep 23 19:39 Makefile
-rwxrwxr-x 1 test test 8520 Sep 23 19:46 process
-rw-rw-r-- 1 test test  187 Sep 23 19:46 process.c
[test@VM-16-11-centos process]$ rm process
[test@VM-16-11-centos process]$ ll
total 8
-rw-rw-r-- 1 test test 106 Sep 23 19:39 Makefile
-rw-rw-r-- 1 test test 187 Sep 23 19:46 process.c

但是程序依旧在运行,这是为什么?

这是因为,磁盘中的文件被删除了,其实和进程关系并不大,进程被运行前就已经被加载到内存中了,因此磁盘上文件的删除对于内存并不会造成决定性的影响,但是如果程序终止想要重新运行,可能就并不可以了,但是在proc文件内,会为用户标出错误提示,说明在磁盘中的可执行程序已经被删掉了

lrwxrwxrwx 1 test test 0 Sep 23 20:09 cwd -> /home/test/process
lrwxrwxrwx 1 test test 0 Sep 23 20:09 exe -> /home/test/process/process (deleted)

那么有几个问题就随之产生了:

  1. 这个父进程是谁,为什么一直不变?

对于这个问题,可以使用ps命令来查看,而结果是bash,也就是命令行解释器

[test@VM-16-11-centos process]$ ps ajx |head -1 && ps ajx | grep 7945
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 7944  7945  7945  7945 pts/0    16488 Ss    1003   0:00 -bash
  1. 父进程的概念如何理解?

关于这个问题,后续和fork一起总结

Linux中创建进程的方式通常有两种:

  1. 命令行中直接启动进程
  2. 通过代码来创建进程

对于第一种很好理解,执行程序./process其实就是启动进程,那第二种是什么?如何理解这个概念?就引出了本篇的核心,系统调用fork

启动进程,本质就是创建进程,一般都是通过父进程创建的

关于如何创建进程,下面用fork来讲述

fork

首先要对fork有一个初步认知,它可以给当前的进程添加一个子进程,它可以使用代码来创建进程,它是属于系统级别的调用:

  • 当用户启动一个进程的时候,如何理解在行为?其实就是在系统重多增加一个进程,操作系统要管理的进程就多了一个
  • 创建一个进程,就是要向系统中申请一些内存,保存当前进程的可执行程序并且要创建这个进程的PCB,也就是task_struct对象,并且将这个对象添加到进程列表中

那么如何来观察现象?

对程序进行改变

#include <stdio.h>
#include <unistd.h>
int main()
{
    printf("Before fork:the pid is %d,the ppid is %d\n",getpid(),getppid());
    fork();
    printf("After fork:the pid is %d,the ppid is %d\n",getpid(),getppid());
    return 0;
}

运行程序

# 运行程序
[test@VM-16-11-centos process]$ ./process 
# 运行结果
Before fork:the pid is 7810,the ppid is 6523
After fork:the pid is 7810,the ppid is 6523
After fork:the pid is 7811,the ppid is 7810

现象很神奇,程序中只打印了一次After fork...,但却输出了两次,并且第二次输出的结果的ppid就是第一次输出的pid,这是不是证明第二次输出的这个7811就是7810的子进程?

答案是肯定的,并且fork之后这两个进程都会执行它们自己的程序,由此展开关于fork的理解

fork的具体描述

使用man指令查看fork的帮助文档内的信息

NAME
       fork - create a child process
SYNOPSIS
       #include <unistd.h>
       pid_t fork(void);

从上面的表述中,可以获取到一些信息,fork的功能就是创建一个子进程,fork函数有两个返回值,给子进程返回0,给父进程返回子进程的pid

为什么要使用fork?

C语言中,写的代码的执行逻辑都是从上向下执行(默认情况下),但是事实上在一些情况下这样的需求满足不了用户的需求,例如要边下载一个电影边播放它,那么这个时候就需要创建一个子进程来帮助实现这个功能,这是单进程所解决不了的,因此级有了fork函数,有了这个函数可以让父进程和子进程做不一样的事,执行不一样的代码,通过fork的返回值就能判断谁是子进程谁是父进程,就可以让它们实现不同的代码片段,执行不同的功能

fork做了些什么?

从表面上看,fork函数在执行后,增加了一个进程,这个进程和原来的父进程会一起执行下去,分别在自己的进程下输出内容(以这个代码为例子),但是这都是表象,从深层次的角度来看,fork的实现过程并不简单

既然是子进程,也属于进程,是进程就要创建程序的PCB,那现在有了关于task_struct,里面的信息在哪里?拷贝的内容是什么?答案是以父进程为模板,为子进程创建PCB,而创建的PCB指向的可执行文件并没有创建,因此这里实现的子进程没有它自己的代码和数据,只是和父进程共享代码和数据,用下图来描述上面的这一系列过程如下:

上图清晰的把前文进行了图示化,创建出的子进程也有自己的PCB,内容来自于父进程的PCB,直接拷贝而来,而它的可执行文件是共享的父进程的可执行文件

fork之后,父子进程会执行同样的代码,fork之前的代码父子进程也都有记录

fork之后会执行同样的代码

  • fork之前的代码可以看到吗?可以看到,父子进程都有前面代码的数据
  • 子进程为什么不从头开始执行?这是由于pc/eip执行fork完毕后,eip指向的是fork后续的代码,eip也会被子进程继承,因此直接执行的是fork之后的代码

进程的独立性如何理解?

关于进程的独立性,可以从下面的角度入手,首先,进程独立性可以从每一个进程都有它自己的PCB来看出,进程之间是不会被相互影响的,但是数据父子是会被修改的,那么可以采用写实拷贝的方法来将这个过程执行下去,进程的代码可以共享,但是进程的数据不可以,数据每一个进程只能拥有一份,不然对于一些全局变量来说,一个进程对于全局变量的改变会使得另外一个进程受到严重的影响,因此上面的图其实并不完全正确,应该这样改良

新创建的子进程的PCB中,对于可执行文件的拥有应该分为两部分,代码片段和数据片段,对于代码片段可以进行共享,但是对于数据片段一定是每一个进程拥有一份独立的数据,这样才能保证进程的独立性

fork之后,父子进程谁先运行?

创建完成子进程,只是开始,系统中有其他进程,父进程和子进程,接下来谁先被执行要看谁先被调度,先被调度的就要先运行,那么有具体的规则吗?没有,这是由操作系统自己来决定的,由每个进程PCB中的调度信息,比如说时间片优先级等等,和调度器算法共同决定谁优先被调用

如何理解fork?

从本质上来讲,fork其实就是一个函数,那么它函数中的内容会有哪些?

  1. 找到父进程的PCB对象
  2. malloc一个PCB用来放子进程
  3. 用父进程的PCB来初始化子进程
  4. 让子进程的PCB指向父进程的代码和数据
  5. 子进程和父进程都加入调度队列开始排队

简单来说,就是创建子进程,将子进程放到调度队列中运行

以上为对fork的初步理解,后续会继续用它实现系统级别的代码

相关文章
|
2月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
110 1
|
4天前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
52 34
|
8天前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
40 16
|
1月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
120 20
|
2月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
121 13
|
2月前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
2月前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
3月前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
3月前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
354 1
|
3月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?