小言_互联网的博客

Linux篇【5】:Linux 进程概念(二)

311人阅读  评论(0)

目录

3.5、查看进程

3.6、通过系统调用接口获取时实进程的标识符

3.7、通过系统调用接口创建子进程 - fork 初识


3.5、查看进程


  
  1. [HJM@hjmlcc ~]$ clear
  2. [HJM@hjmlcc ~]$ pwd
  3. /home/HJM
  4. [HJM@hjmlcc ~]$ ls
  5. [HJM@hjmlcc ~]$ touch mytest.c
  6. [HJM@hjmlcc ~]$ ls
  7. mytest.c
  8. [HJM@hjmlcc ~]$ touch Makefile
  9. [HJM@hjmlcc ~]$ ls
  10. Makefile mytest.c
  11. [HJM@hjmlcc ~]$ vim Makefile
  12. [HJM@hjmlcc ~]$ cat Makefile
  13. mytest:mytest.c
  14. gcc mytest.c -o mytest
  15. .PHONY:clean
  16. clean:
  17. rm -f mytest
  18. [HJM@hjmlcc ~]$ vim mytest.c
  19. [HJM@hjmlcc ~]$ cat mytest.c
  20. #include<stdio.h>
  21. #include<unistd.h>
  22. int main()
  23. {
  24. while( 1) //死循环、
  25. {
  26. printf( "I am a process!\n");
  27. sleep( 1);
  28. }
  29. return 0;
  30. }
  31. [HJM@hjmlcc ~]$ make
  32. gcc mytest.c -o mytest
  33. [HJM@hjmlcc ~]$ ls
  34. Makefile mytest mytest.c
  35. //此处的 mytest 是可执行程序,是一个普通文件,存在于磁盘上,该磁盘指的并不是在我们笔记本中的磁
  36. //盘上,而是存在于云服务器上的磁盘中、
  37. [HJM@hjmlcc ~]$ ldd mytest
  38. linux-vdso.so .1 => ( 0x00007ffcba19d000)
  39. /$LIB/libonion.so => /lib64/libonion. so ( 0x00007f18b638f000)
  40. libc.so .6 => /lib64/libc.so .6 ( 0x00007f18b5ea8000)
  41. libdl.so .2 => /lib64/libdl.so .2 ( 0x00007f18b5ca4000)
  42. /lib64/ld-linux-x86 -64.so .2 ( 0x00007f18b6276000)
  43. [HJM@hjmlcc ~]$ file mytest
  44. mytest: ELF 64-bit LSB executable, x86 -64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6 .32, BuildID[sha1]=e1ce1242da6edeb0fd0c5a1c316cbd303ba05c73, not stripped
  45. [HJM@hjmlcc ~]$ ./mytest
  46. //之前我们称上述操作为将可执行程序mytest运行起来,现在通过上述操作便可形成一个进程,因此我们可
  47. //以称上述操作是:一个关于可执行程序mytest所形成的进程、
  48. I am a process!
  49. I am a process!
  50. I am a process!
  51. I am a process!
  52. I am a process!
  53. I am a process!
  54. I am a process!
  55. I am a process!
  56. I am a process!
  57. I am a process!
  58. I am a process!
  59. ...
  60. ...

在 Linux 操作系统中,如何查看正在运行(时实启动)的进程及其信息呢?

方法一:


  
  1. [HJM@hjmlcc ~]$ clear
  2. [HJM@hjmlcc ~]$ ps ajx //a:all,j:job,x:以特定格式进行显示,或者是: ps axj ,顺序无所谓、
  3. //把 Linux 操作系统中所有的正在运行的时实启动的进程及其信息全部显示出来、
  4. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  5. 0 1 1 1 ? -1 Ss 0 17: 46 /usr/lib/sys
  6. 0 2 0 0 ? -1 S 0 0: 03 [kthreadd]
  7. 2 4 0 0 ? -1 S< 0 0: 00 [kworker/ 0: 0
  8. 2 18 0 0 ? -1 S 0 0: 00 [kdevtmpfs]
  9. 2 19 0 0 ? -1 S< 0 0: 00 [netns]
  10. 2 20 0 0 ? -1 S 0 0: 02 [khungtaskd]
  11. ...
  12. ...
  13. 2 30148 0 0 ? -1 S 0 0: 00 [kworker/ 0: 1
  14. 1 30373 30373 30373 ? -1 Ssl 1002 0: 00 /home/HJM/.V
  15. 1 30380 30380 30380 ? -1 Ssl 1002 0: 00 /home/HJM/.V
  16. 30380 30391 30380 30380 ? -1 Z 1002 0: 00 [querydb] <d
  17. 1 31068 31068 31068 ? -1 Ssl 1002 0: 00 /home/HJM/.V
  18. 1 31076 31076 31076 ? -1 Ssl 1002 0: 00 /home/HJM/.V
  19. 31076 31087 31076 31076 ? -1 Z 1002 0: 00 [querydb] <d
  20. 2 31438 0 0 ? -1 S 0 0: 00 [kworker/ 0: 3
  21. 2 32544 0 0 ? -1 S 0 0: 01 [kworker/ 0: 0
  22. [HJM@hjmlcc ~]$ ps ajx | grep 'mytest'
  23. 10484 12399 12399 10484 pts/ 0 12399 S+ 1002 0: 00 ./mytest
  24. 12404 13061 13060 12404 pts/ 1 13060 S+ 1002 0: 00 grep --color=automytest
  25. //在Linux操作系统中所有的正在运行的时实启动的进程及其信息中查找关于可执行程序mytest所形成的
  26. //进程及其信息,若关于可执行程序mytest所形成的进程正在运行或时实启动,则会把关于可执行程序mytes
  27. //t所形成的进程及其信息显式出来,若关于可执行程序mytest所形成的进程未正在运行或未时实启动,则
  28. //不会把关于可执行程序mytest所形成的进程及其信息显式出来、
  29. //对于上述指令行而言,有关可执行程序ps所形成的进程和有关可执行程序grep所形成的进程一直都是在
  30. //运行(时实启动)的,有关可执行程序mytest所形成的进程可能正在运行(时实启动),也有可能没有正在运
  31. //行(时实启动),由于上面是对有关可执行程序mytest形成的进程及其信息进行的搜索,按理说只需要显式
  32. //出来有关可执行程序mytest形成的进程是否正在运行(时实启动)即可,但此处还把正在运行(时实启动)
  33. //的有关可执行程序grep所形成的进程及其信息显示了出来,其次,虽然这里并未显式出来正在运行(时实
  34. //启动的)有关可执行程序ps所形成的进程及其信息,但要知道,有关可执行程序ps所形成的进程一直正在
  35. //运行(时实启动),只不过这里并没有把该进程及其信息显式出来而已,由于此处还默认显式出来正在运行
  36. //(时实启动的)有关可执行程序grep所形成的进程及其信息,若不想显式该进程及其信息的话,可以通过下
  37. //述操作:
  38. [HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
  39. //即:上述操作中grep -v的后面只要匹配到某一个有关某一个可执行程序所形成的进程所对应的可执行程
  40. //序的名字,则该进程及其信息一律不进行显式,此时我们知道,对于有关可执行程序grep所形成的进程而
  41. //言是一直在运行(时实启动)的,按理说在下面会显示出来该进程及其信息,但是,上述操作中又有grep -v
  42. // grep,所以在下面结果中就不再进行显示该进程及其信息了、
  43. 10484 23680 23680 10484 pts/ 0 23680 S+ 1002 0: 00 ./mytest
  44. [HJM@hjmlcc ~]$

    我们自己写的程序代码,当经过编译链接之后则形成一个可执行程序,运行该可执行程序之后就得到一个进程,同样,别人写的程序代码当编译链接之后也会形成一个可执行程序,运行该可执行程序之后也得到一个进程,比如:ls,pwd,touch,grep,chgrp,chown,mkdir,rm ... 等等指令,这些指令在本质上就是可执行程序,当我们执行这些指令时,本质上就是运行了这些可执行程序,因此当运行这些可执行程序时,也会得到这些可执行程序各自对应的进程,Linux 系统中的大部分指令(可执行程序)存在于云服务器中的磁盘里面,可以通过指令:ls /usr/bin/* 查看,如下所示,这些大部分指令(可执行程序)就等价于 Windows 系统中 C 盘里的应用程序(可执行程序)、


  
  1. [HJM@hjmlcc ~]$ ls /usr/bin /*
  2. //usr:用户,bin:二进制、
  3. /usr/bin/[
  4. /usr/bin/a2p
  5. /usr/bin/abrt-action-analyze-backtrace
  6. /usr/bin/abrt-action-analyze-c
  7. /usr/bin/abrt-action-analyze-ccpp-local
  8. /usr/bin/abrt-action-analyze-core
  9. /usr/bin/abrt-action-analyze-oops
  10. /usr/bin/abrt-action-analyze-python
  11. /usr/bin/abrt-action-analyze-vmcore
  12. /usr/bin/abrt-action-analyze-vulnerability
  13. /usr/bin/abrt-action-analyze-xorg
  14. /usr/bin/abrt-action-check-oops-for-hw-err
  15. ...
  16. ...
  17. /usr/bin/zip
  18. /usr/bin/zipcloak
  19. /usr/bin/zipgrep
  20. /usr/bin/zipinfo
  21. /usr/bin/zipnote
  22. /usr/bin/zipsplit
  23. /usr/bin/zless
  24. /usr/bin/zmore
  25. /usr/bin/znew
  26. /usr/bin/zsoelim
  27. [HJM@hjmlcc ~]$
  28. //之前我们执行的所有的指令,本质上都是在运行可执行程序,则都会形成这些可执行程序对应的进程,只不
  29. //过像:ls,pwd等等这些指令,在执行时,也相当于在运行可执行程序,因此则都会形成他们对应的进程,但
  30. //是他们对应的进程的生命周期很短就结束了,即当我执行完这些指令时,由这些指令所形成的进程很快就
  31. //结束了,在我通过方法查看正在运行或时实启动的进程及其信息之前,由这些指令所形成的进程就已经结
  32. //束了,所以当在查看正在运行或时实启动的进程及其信息时,就看不到由这些指令所形成的进程及其信
  33. //息了、
  34. //在 Windows 系统中,当我们双击 CF 的快捷方式,而该快捷方式指向了 CF 的可执行程序,所以就相当
  35. //于在双击 CF 的可执行程序,即就相当于在运行 CF 的可执行程序,因此便形成了一个与它对应的进程,
  36. //就可以愉快的玩游戏了、

方法二:

    操作系统是进程的管理者,每一个正在运行(时实启动)的进程在 Linux 操作系统中都会存在唯一的一个与之对应的标识符,这个唯一的标识符就是所谓的 PID ,即:Process ID 、


  
  1. [HJM@hjmlcc ~]$ ps ajx | grep 'mytest'
  2. 12404 3406 3405 12404 pts/ 1 3405 S+ 1002 0: 00 grep --color= auto mytest
  3. 10484 31395 31395 10484 pts/ 0 31395 S+ 1002 0: 00 ./mytest
  4. [HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
  5. 10484 31395 31395 10484 pts/ 0 31395 S+ 1002 0: 00 ./mytest
  6. [HJM@hjmlcc ~]$ ps ajx | head -1 //是1不是l,代表前1行、
  7. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  8. [HJM@hjmlcc ~]$ ps ajx | head -5
  9. //把 Linux 操作系统中所有的正在运行的时实启动的进程及其信息的前 5 行全部显示出来,其中第一行
  10. //代表进程属性的名称、
  11. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  12. 0 1 1 1 ? -1 Ss 0 17: 59 /usr/lib/systemd/systemd --system --deserialize 23
  13. 0 2 0 0 ? -1 S 0 0: 03 [kthreadd]
  14. 2 4 0 0 ? -1 S< 0 0: 00 [kworker/ 0: 0H]
  15. 2 6 0 0 ? -1 S 0 2: 20 [ksoftirqd/ 0]
  16. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  17. //当指令行:ps ajx | head -1执行成功后,再执行指令行:head -1 && ps ajx | grep 'mytest' | grep
  18. // -v grep,若前面的指令行执行失败,则后面的指令行就不再进行执行了、
  19. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  20. 10484 31395 31395 10484 pts/ 0 31395 S+ 1002 0: 00 ./mytest
  21. //由此可知,有关可执行程序mytest所形成的进程的 PID 是31395、
  22. [HJM@hjmlcc ~]$ ls /proc/ 31395
  23. attr cmdline environ io mem ns pagemap sched stack task
  24. autogroup comm exe limits mountinfo numa_maps patch_state schedstat stat timers
  25. auxv coredump_filter fd loginuid mounts oom_adj personality sessionid statm uid_map
  26. cgroup cpuset fdinfo map_files mountstats oom_score projid_map setgroups status wchan
  27. clear_refs cwd gid_map maps net oom_score_adj root smaps syscall
  28. [HJM@hjmlcc ~]$ ls /proc/ 31395 -d
  29. /proc/ 31395
  30. //此时如果把有关可执行程序mytest所形成的进程结束掉,然后再执行指令:ls /proc/31395 -d时,得到
  31. //如下结果,这是因为,根目录下的proc目录中存放的是当前 Linux 操作系统中正在运行或时实启动的进
  32. //程及其信息、
  33. [HJM@hjmlcc ~]$ ls /proc/ 31395 -d
  34. ls: cannot access /proc/ 31395: No such file or directory
  35. [HJM@hjmlcc ~]$
  36. //当把有关可执行程序mytest所形成的进程再次启动时,若再执行上述指令:ls /proc/31395 -d,会发现
  37. //得到的结果是:ls: cannot access /proc/31395: No such file or directory,如下所示:
  38. [HJM@hjmlcc ~]$ ls /proc/ 31395 -d
  39. ls: cannot access /proc/ 31395: No such file or directory
  40. [HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
  41. 10484 27073 27073 10484 pts/ 0 27073 S+ 1002 0: 00 ./mytest
  42. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  43. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  44. 10484 27073 27073 10484 pts/ 0 27073 S+ 1002 0: 00 ./mytest
  45. //这是因为:当我们重新启动有关可执行程序mytest所形成的进程时,此次的该进程与前一次启动有关可执行
  46. //程序mytest所形成的进程并不是同一个进程,后者相对于前者而言是一个新的进程,所以此次的有关可执
  47. //行程序mytest所形成的进程的 PID 也会发生改变,Linux 操作系统会为其重新分配 PID ,由31395变成
  48. //了27073、
  49. [HJM@hjmlcc ~]$ ls /proc/ 27073 -d
  50. /proc/ 27073
  51. [HJM@hjmlcc ~]$ ls /proc/ 27073
  52. //以下则是有关可执行程序mytest所形成的进程的所有的属性数据信息的集合,时实的以文件的方式进行
  53. //显示、
  54. attr cmdline environ io mem ns pagemap sched stack task
  55. autogroup comm exe limits mountinfo numa_maps patch_state schedstat stat timers
  56. auxv coredump_filter fd loginuid mounts oom_adj personality sessionid statm uid_map
  57. cgroup cpuset fdinfo map_files mountstats oom_score projid_map setgroups status wchan
  58. clear_refs cwd gid_map maps net oom_score_adj root smaps syscall
  59. [HJM@hjmlcc ~]$ ls /proc/ 27073 -al
  60. total 0
  61. dr-xr-xr-x 9 HJM HJM 0 Nov 12 19: 09 .
  62. dr-xr-xr-x 124 root root 0 Jul 28 11: 13 ..
  63. dr-xr-xr-x 2 HJM HJM 0 Nov 12 19: 15 attr
  64. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 15 autogroup
  65. -r-------- 1 HJM HJM 0 Nov 12 19: 15 auxv
  66. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 cgroup
  67. --w------- 1 HJM HJM 0 Nov 12 19: 15 clear_refs
  68. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 09 cmdline
  69. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 15 comm
  70. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 15 coredump_filter
  71. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 cpuset
  72. lrwxrwxrwx 1 HJM HJM 0 Nov 12 19: 09 cwd -> /home/HJM
  73. //上述代表有关可执行程序mytest所形成的的进程当前的工作路径、
  74. -r-------- 1 HJM HJM 0 Nov 12 19: 09 environ
  75. lrwxrwxrwx 1 HJM HJM 0 Nov 12 19: 09 exe -> /home/HJM/mytest
  76. //上述代表的就是有关可执行程序mytest所形成的的进程对应的在云服务器中的磁盘中的可执行程序mytes
  77. //t所在的路径、
  78. ...
  79. ...
  80. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 statm
  81. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 09 status
  82. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 syscall
  83. dr-xr-xr-x 3 HJM HJM 0 Nov 12 19: 15 task
  84. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 timers
  85. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 15 uid_map
  86. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 15 wchan
  87. [HJM@hjmlcc ~]$
  88. //进程的 PID 以及当前路径等等都属于进程的属性数据信息,都属于系统数据,都在描述该进程的进程控
  89. //制块(PCB),在 Linux 系统下的 task_struct 结构体中、
  90. //在之前,我们认为当前路径就是程序或者源代码所在的路径,其实本质上并不准确,真正意义上的当前路径
  91. //指的就是:进程当前所在(工作)的路径,当进程启动时,这个路径由进程自己进行维护、
  92. //如下所示:
  93. //新建会话0:
  94. [HJM@hjmlcc ~]$ ls
  95. code Makefile mytest.c
  96. [HJM@hjmlcc ~]$ cat mytest.c
  97. #include<stdio.h>
  98. #include<unistd.h>
  99. int main()
  100. {
  101. FILE* fp= fopen( "log.txt", "w");
  102. //由此可知,log.txt前面并没有指定路径,则默认为当前路径下,如果在当前路径下不存在普通文
  103. //件log.txt,则会新建一个名为log.txt的普通文件、
  104. while( 1)
  105. {
  106. printf( "I am a process!\n");
  107. sleep( 1);
  108. }
  109. return 0;
  110. }
  111. [HJM@hjmlcc ~]$ make
  112. gcc mytest.c -o mytest
  113. [HJM@hjmlcc ~]$ ls
  114. code Makefile mytest mytest.c
  115. [HJM@hjmlcc ~]$ mv mytest code
  116. [HJM@hjmlcc ~]$ ls
  117. code Makefile mytest.c
  118. [HJM@hjmlcc ~]$ cd code
  119. [HJM@hjmlcc code]$ ls
  120. mytest
  121. [HJM@hjmlcc code]$ ./mytest
  122. I am a process!
  123. I am a process!
  124. I am a process!
  125. I am a process!
  126. I am a process!
  127. I am a process!
  128. I am a process!
  129. I am a process!
  130. I am a process!
  131. ...
  132. ...
  133. //新建会话1:
  134. [HJM@hjmlcc ~]$ pwd
  135. /home/HJM
  136. [HJM@hjmlcc ~]$ ls
  137. code Makefile mytest.c
  138. [HJM@hjmlcc ~]$ cd code
  139. [HJM@hjmlcc code]$ ls
  140. mytest
  141. [HJM@hjmlcc code]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  142. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  143. 10484 1738 1738 10484 pts/ 0 1738 S+ 1002 0: 00 ./mytest
  144. [HJM@hjmlcc code]$ ls /proc/ 1738
  145. attr environ mem pagemap stack
  146. autogroup exe mountinfo patch_state stat
  147. auxv fd mounts personality statm
  148. cgroup fdinfo mountstats projid_map status
  149. clear_refs gid_map net root syscall
  150. cmdline io ns sched task
  151. comm limits numa_maps schedstat timers
  152. coredump_filter loginuid oom_adj sessionid uid_map
  153. cpuset map_files oom_score setgroups wchan
  154. cwd maps oom_score_adj smaps
  155. [HJM@hjmlcc code]$ ls /proc/ 1738 -d
  156. /proc/ 1738
  157. [HJM@hjmlcc code]$ ls /proc/ 1738 -al
  158. total 0
  159. dr-xr-xr-x 9 HJM HJM 0 Nov 12 19: 44 .
  160. dr-xr-xr-x 126 root root 0 Jul 28 11: 13 ..
  161. dr-xr-xr-x 2 HJM HJM 0 Nov 12 19: 45 attrer
  162. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 45 cpuset
  163. lrwxrwxrwx 1 HJM HJM 0 Nov 12 19: 44 cwd -> /home/HJM/code //当前路径、
  164. -r-------- 1 HJM HJM 0 Nov 12 19: 45 environ
  165. lrwxrwxrwx 1 HJM HJM 0 Nov 12 19: 44 exe -> /home/HJM/code/mytest
  166. lrwxrwxrwx 1 HJM HJM 0 Nov 12 19: 44 root -> /
  167. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 45 sched
  168. ...
  169. ...
  170. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 45 syscall
  171. dr-xr-xr-x 3 HJM HJM 0 Nov 12 19: 45 task
  172. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 45 timers
  173. -rw-r--r-- 1 HJM HJM 0 Nov 12 19: 45 uid_map
  174. -r--r--r-- 1 HJM HJM 0 Nov 12 19: 45 wchan
  175. [HJM@hjmlcc ~]$
  176. //新建会话0:
  177. ...
  178. ...
  179. I am a process!
  180. I am a process!
  181. I am a process!
  182. I am a process!
  183. I am a process!
  184. ^C
  185. [HJM@hjmlcc code]$ ls
  186. log.txt mytest
  187. //注意:
  188. //1、
  189. [HJM@hjmlcc ~]$ ls
  190. code Makefile mytest.c
  191. [HJM@hjmlcc ~]$ cd code
  192. [HJM@hjmlcc code]$ ls
  193. [HJM@hjmlcc code]$ cd ..
  194. [HJM@hjmlcc ~]$ ls
  195. code Makefile mytest.c
  196. [HJM@hjmlcc ~]$ make
  197. gcc mytest.c -o mytest
  198. [HJM@hjmlcc ~]$ ls
  199. code Makefile mytest mytest.c
  200. [HJM@hjmlcc ~]$ make clean
  201. rm -f mytest
  202. [HJM@hjmlcc ~]$ ls
  203. code Makefile mytest.c
  204. [HJM@hjmlcc ~]$
  205. //2、
  206. [HJM@hjmlcc ~]$ ls
  207. code Makefile mytest.c
  208. [HJM@hjmlcc ~]$ cd code
  209. [HJM@hjmlcc code]$ ls
  210. [HJM@hjmlcc code]$ cd ..
  211. [HJM@hjmlcc ~]$ ls
  212. code Makefile mytest.c
  213. [HJM@hjmlcc ~]$ make
  214. gcc mytest.c -o mytest
  215. [HJM@hjmlcc ~]$ ls
  216. code Makefile mytest mytest.c
  217. [HJM@hjmlcc ~]$ mv mytest code
  218. [HJM@hjmlcc ~]$ ls
  219. code Makefile mytest.c
  220. [HJM@hjmlcc ~]$ cd code
  221. [HJM@hjmlcc code]$ ls
  222. mytest
  223. [HJM@hjmlcc code]$ make clean
  224. make: *** No rule to make target `clean '. Stop. //无法删除可执行程序mytest、
  225. [HJM@hjmlcc code]$ cd ..
  226. [HJM@hjmlcc ~]$ ls
  227. code Makefile mytest.c
  228. [HJM@hjmlcc ~]$ make clean
  229. rm -f mytest
  230. [HJM@hjmlcc ~]$ ls
  231. code Makefile mytest.c
  232. [HJM@hjmlcc ~]$ cd code
  233. [HJM@hjmlcc code]$ ls
  234. mytest //仍没有删除掉可执行程序mytest、
  235. [HJM@hjmlcc code]$

  
  1. //在讲解粘滞位时,tmp目录文件是一个共享的目录文件,里面存放的是临时文件、
  2. //proc目录文件是 Linux 系统根目录下的一个目录,proc:process,proc:内存文件系统,该目录文件中存
  3. //放的是当前操作系统中正在运行或时实运行的进程及其信息、
  4. [HJM@hjmlcc ~]$ ls /
  5. bin boot data dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
  6. [HJM@hjmlcc ~]$
  7. [HJM@hjmlcc ~]$ ls /
  8. bin boot data dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
  9. [HJM@hjmlcc ~]$ ls /proc
  10. 1 12535 16515 20344 25287 28 31335 50 7 cpuinfo irq modules swaps
  11. 10 13 16526 20730 255 29 31368 51 8 crypto kallsyms mounts sys
  12. 10470 1389 16792 20827 256 290 36 52 8227 devices kcore mtrr sysrq-trigger
  13. 10483 1390 18 21 26 291 37 577 9 diskstats keys net sysvipc
  14. 10484 14 18820 21813 262 292 3756 6 925 dma key-users pagetypeinfo timer_list
  15. 11 1521 18853 22 266 29633 38 646 991 driver kmsg partitions timer_stats
  16. 1164 1552 19 23 267 30123 387 648 993 execdomains kpagecount sched_debug tty
  17. 1178 1558 19039 24 269 30373 3871 65 acpi fb kpageflags schedstat uptime
  18. 12 1559 19089 24315 27 30380 39 651 buddyinfo filesystems loadavg scsi version
  19. 1207 1575 197 2472 270 30391 4 6515 bus fs locks self vmallocinfo
  20. 1222 16 2 2485 27176 31068 407 652 cgroups interrupts mdstat slabinfo vmstat
  21. 12404 160 20 2496 27184 31076 47 654 cmdline iomem meminfo softirqs xpmem
  22. 12524 16503 20337 25 27195 31087 49 659 consoles ioports misc stat zoneinfo
  23. [HJM@hjmlcc ~]$ ls /proc -l
  24. total 0
  25. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 1
  26. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 10
  27. dr-xr-xr-x 9 root root 0 Nov 12 14: 59 10470
  28. dr-xr-xr-x 9 HJM HJM 0 Nov 12 14: 59 10483
  29. dr-xr-xr-x 9 HJM HJM 0 Nov 12 14: 59 10484
  30. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 11
  31. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 1164
  32. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 1178
  33. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 12
  34. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 1207
  35. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 8
  36. dr-xr-xr-x 9 root root 0 Nov 12 14: 48 8227
  37. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 9
  38. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 925
  39. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 991
  40. dr-xr-xr-x 9 root root 0 Jul 28 11: 13 993
  41. dr-xr-xr-x 2 root root 0 Nov 12 16: 47 acpi
  42. -r--r--r-- 1 root root 0 Nov 12 16: 47 buddyinfo
  43. dr-xr-xr-x 4 root root 0 Nov 12 16: 47 bus
  44. -r--r--r-- 1 root root 0 Nov 12 16: 47 cgroups
  45. -r--r--r-- 1 root root 0 Nov 12 16: 47 cmdline
  46. -r--r--r-- 1 root root 0 Nov 12 16: 47 consoles
  47. -r--r--r-- 1 root root 0 Nov 12 16: 47 cpuinfo
  48. -r--r--r-- 1 root root 0 Nov 12 16: 47 crypto
  49. -r--r--r-- 1 root root 0 Nov 12 16: 47 devices
  50. ...
  51. ...
  52. -r--r--r-- 1 root root 0 Nov 12 16: 47 version
  53. -r-------- 1 root root 0 Nov 12 16: 47 vmallocinfo
  54. -r--r--r-- 1 root root 0 Nov 12 16: 47 vmstat
  55. dr-xr-xr-x 2 root root 0 Nov 12 16: 47 xpmem
  56. -r--r--r-- 1 root root 0 Nov 12 16: 47 zoneinfo
  57. [HJM@hjmlcc ~]$

 方法三:


  
  1. //一、
  2. //新建会话0:
  3. [HJM@hjmlcc ~]$ ls
  4. a.out lcc.c Makefile process process.c
  5. [HJM@hjmlcc ~]$ ./process
  6. I am a process: 9684
  7. I am a process: 9684
  8. I am a process: 9684
  9. I am a process: 9684
  10. I am a process: 9684
  11. ...
  12. ...
  13. //新建会话1: //a,u,x三者的顺序无所谓、
  14. [HJM@hjmlcc ~]$ ls
  15. a.out lcc.c Makefile process process.c
  16. [HJM@hjmlcc ~]$ ps aux | head -1 && ps aux | grep 'process' | grep -v grep
  17. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  18. HJM 9684 0.0 0.0 7332 380 pts/ 0 S+ 17: 31 0: 00 ./process
  19. [HJM@hjmlcc ~]$
  20. //2、
  21. //新建会话0:
  22. ...
  23. ...
  24. I am a process: 9684
  25. I am a process: 9684
  26. I am a process: 9684
  27. I am a process: 9684
  28. ^C
  29. [HJM@hjmlcc ~]$
  30. //新建会话1:
  31. [HJM@hjmlcc ~]$ ls
  32. a.out lcc.c Makefile process process.c
  33. [HJM@hjmlcc ~]$ ps aux | head -1 && ps aux | grep 'process' | grep -v grep
  34. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  35. [HJM@hjmlcc ~]$

拓展:


   
  1. [HJM@hjmlcc ~]$ pwd
  2. /home/HJM
  3. [HJM@hjmlcc ~]$ ls
  4. //显式出当前路径(目录)下的所有内容、
  5. Makefile mytest mytest.c
  6. [HJM@hjmlcc ~]$ ls / //此处的 / 代表根目录、
  7. //显示出根目录下的所有内容、
  8. bin boot data dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
  9. [HJM@hjmlcc ~]$ ls /proc //此处的 / 代表根目录、
  10. //显示出根目录下的proc目录中的所有内容、
  11. 1 12535 16515 20344 25287 28 36 52 7 cpuinfo irq modules swaps
  12. 10 13 16526 20730 255 29 37 577 8 crypto kallsyms mounts sys
  13. 10470 1389 16792 20827 256 290 3756 6 8227 devices kcore mtrr sysrq-trigger
  14. 10483 1390 18 21 26 291 38 646 9 diskstats keys net sysvipc
  15. 10484 14 18820 21813 262 292 387 648 925 dma key-users pagetypeinfo timer_list
  16. 11 1521 18853 22 266 30373 3871 65 991 driver kmsg partitions timer_stats
  17. 1164 1552 19 23 267 30380 39 650 993 execdomains kpagecount sched_debug tty
  18. 1178 1558 19039 24 269 30391 4 651 acpi fb kpageflags schedstat uptime
  19. 12 1559 19089 24315 27 31068 407 6515 buddyinfo filesystems loadavg scsi version
  20. 1207 1575 197 2472 270 31076 47 652 bus fs locks self vmallocinfo
  21. 1222 16 2 2485 27176 31087 49 654 cgroups interrupts mdstat slabinfo vmstat
  22. 12404 160 20 2496 27184 31395 50 659 cmdline iomem meminfo softirqs xpmem
  23. 12524 16503 20337 25 27195 32061 51 678 consoles ioports misc stat zoneinfo
  24. [HJM@hjmlcc ~]$ ls /home/HJM //此处只有第一个 / 代表根目录、
  25. //显示出根目录下的home目录下的HJM目录中的所有内容、
  26. Makefile mytest mytest.c
  27. [HJM@hjmlcc ~]$
  28. // cd 指令的用法也类似于上面所示、

3.6、通过系统调用接口获取时实进程的标识符

    通过Linux操作系统所提供的系统调用接口获取正在进行(时实启动)的进程的进程ID(PID)和该进程的父进程ID(PPID)、

如何获取正在运行(时实启动)的进程的 PID 呢 ?


  
  1. //当启动一个进程,则该进程就是正在运行(时实启动)的,则操作系统会为该进程分配一个 PID 、
  2. [HJM@hjmlcc ~]$ man 2 getpid //查看Linux操作系统提供的系统调用接口、
  3. //由于Linux操作系统是使用C语言写的,故Linux操作系统所提供的系统调用接口在本质上就是C语言函数
  4. //调用接口,这属于Linux操作系统的系统调用接口,在Windows系统下使用该Linux系统下的该系统调用
  5. //接口,应该是不可以的、
  6. GETPID( 2) Linux Programmer ' s Manual GETPID(2)
  7. NAME
  8. getpid, getppid - get process identification
  9. SYNOPSIS
  10. #include <sys/types.h>
  11. #include <unistd.h>
  12. pid_t getpid(void); // pid_t 等价于 size_t 、
  13. pid_t getppid(void);
  14. DESCRIPTION
  15. getpid() returns the process ID of the calling process. (This is often used by routines that generate unique temporary filenames.)
  16. getppid() returns the process ID of the parent of the calling process.
  17. ERRORS
  18. These functions are always successful.
  19. CONFORMING TO
  20. POSIX.1-2001, 4.3BSD, SVr4.
  21. NOTES
  22. Since glibc version 2.3.4, the glibc wrapper function for getpid() caches PIDs, so as to avoid additional system calls when a process calls
  23. getpid() repeatedly. Normally this caching is invisible, but its correct operation relies on support in the wrapper functions for fork(2),
  24. vfork(2), and clone(2): if an application bypasses the glibc wrappers for these system calls by using syscall(2), then a call to getpid() in
  25. the child will return the wrong value (to be precise: it will return the PID of the parent process). See also clone(2) for discussion of a
  26. case where getpid() may return the wrong value even when invoking clone(2) via the glibc wrapper function.
  27. SEE ALSO
  28. clone(2), fork(2), kill(2), exec(3), mkstemp(3), tempnam(3), tmpfile(3), tmpnam(3), credentials(7)
  29. COLOPHON
  30. This page is part of release 3.53 of the Linux man-pages project. A description of the project, and information about reporting bugs, can be
  31. found at http://www.kernel.org/doc/man-pages/.
  32. Manual page getpid(2) line 1 (press h for help or q to quit)q

  
  1. //新建会话0:
  2. [HJM@hjmlcc ~]$ ls
  3. code Makefile mytest.c
  4. [HJM@hjmlcc ~]$ vim mytest.c
  5. [HJM@hjmlcc ~]$ cat mytest.c
  6. #include<stdio.h>
  7. #include<sys/types.h>
  8. #include<unistd.h>
  9. int main()
  10. {
  11. while( 1)
  12. {
  13. printf( "I am a process!,pid:%d\n", getpid());
  14. sleep( 1);
  15. }
  16. return 0;
  17. }
  18. [HJM@hjmlcc ~]$ make
  19. gcc mytest.c -o mytest
  20. [HJM@hjmlcc ~]$ ls
  21. code Makefile mytest mytest.c
  22. [HJM@hjmlcc ~]$ ./mytest
  23. I am a process!,pid: 9457
  24. I am a process!,pid: 9457
  25. I am a process!,pid: 9457
  26. I am a process!,pid: 9457
  27. I am a process!,pid: 9457
  28. I am a process!,pid: 9457
  29. ...
  30. ...
  31. //新建会话1:
  32. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  33. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  34. 5899 9457 9457 5899 pts/ 0 9457 S+ 1002 0: 00 ./mytest //9457、
  35. [HJM@hjmlcc ~]$

如何结束掉正在运行(时实启动)的进程呢?

方法一:


  
  1. [HJM@hjmlcc ~]$ ls
  2. Makefile mytest mytest.c
  3. [HJM@hjmlcc ~]$ ./mytest
  4. I am a process!,pid: 10001
  5. I am a process!,pid: 10001
  6. I am a process!,pid: 10001
  7. I am a process!,pid: 10001
  8. I am a process!,pid: 10001
  9. I am a process!,pid: 10001
  10. I am a process!,pid: 10001
  11. ^C
  12. [HJM@hjmlcc ~]$
  13. //使用热键 ctrl+c ,即可结束掉正在运行(时实启动)的进程、

方法二:


  
  1. //新建会话0:
  2. [HJM@hjmlcc ~]$ ls
  3. Makefile mytest mytest.c
  4. [HJM@hjmlcc ~]$ ./mytest
  5. I am a process!,pid: 10470
  6. I am a process!,pid: 10470
  7. I am a process!,pid: 10470
  8. I am a process!,pid: 10470
  9. ...
  10. ...
  11. //新建会话1:
  12. [HJM@hjmlcc ~]$ ls
  13. Makefile mytest mytest.c
  14. [HJM@hjmlcc ~]$ kill -9 10470
  15. //向正在运行(时实启动)的进程发送9号信号,在后期信号中会进行具体的阐述,10470就是我们要结束掉的
  16. //正在运行(时实启动)的进程的PID、
  17. [HJM@hjmlcc ~]$
  18. //新建会话0:
  19. ...
  20. ...
  21. I am a process!,pid: 10470
  22. I am a process!,pid: 10470
  23. I am a process!,pid: 10470
  24. I am a process!,pid: 10470
  25. Killed
  26. [HJM@hjmlcc ~]$
  27. //此时正在运行(时实启动)的有关可执行程序mytest所形成的进程就被结束掉了、

  
  1. [HJM@hjmlcc ~]$ man 2 getppid
  2. GETPID(2) Linux Programmer's Manual GETPID(2)
  3. NAME
  4. getpid, getppid - get process identification
  5. SYNOPSIS
  6. #include <sys/types.h>
  7. #include <unistd.h>
  8. pid_t getpid(void);
  9. pid_t getppid(void);
  10. DESCRIPTION
  11. getpid() returns the process ID of the calling process. (This is
  12. often used by routines that generate unique temporary filenames.)
  13. getppid() returns the process ID of the parent of the calling
  14. process.
  15. ERRORS
  16. These functions are always successful.
  17. CONFORMING TO
  18. POSIX.1-2001, 4.3BSD, SVr4.
  19. NOTES
  20. Since glibc version 2.3.4, the glibc wrapper function for getpid()
  21. caches PIDs, so as to avoid additional system calls when a process
  22. calls getpid() repeatedly. Normally this caching is invisible,
  23. but its correct operation relies on support in the wrapper func‐
  24. tions for fork(2), vfork(2), and clone(2): if an application
  25. bypasses the glibc wrappers for these system calls by using
  26. syscall(2), then a call to getpid() in the child will return the
  27. wrong value (to be precise: it will return the PID of the parent
  28. process). See also clone(2) for discussion of a case where get‐
  29. pid() may return the wrong value even when invoking clone(2) via
  30. Manual page getppid(2) line 1 (press h for help or q to quit)q

  
  1. //新建会话0:
  2. [HJM@hjmlcc ~]$ ls
  3. Makefile mytest mytest.c
  4. [HJM@hjmlcc ~]$ cat mytest.c
  5. #include<stdio.h>
  6. #include<sys/types.h>
  7. #include<unistd.h>
  8. int main()
  9. {
  10. while( 1)
  11. {
  12. printf( "I am a process!,pid:%d,ppid:%d\n", getpid(), getppid());
  13. sleep( 1);
  14. }
  15. return 0;
  16. }
  17. [HJM@hjmlcc ~]$ make
  18. gcc mytest.c -o mytest
  19. [HJM@hjmlcc ~]$ ls
  20. Makefile mytest mytest.c
  21. [HJM@hjmlcc ~]$ ./mytest
  22. //有关可执行程序mytest所形成的进程的进程ID(PID)为12260,而该进程的父进程ID(PPID)为5899、
  23. I am a process!,pid: 12260,ppid: 5899
  24. I am a process!,pid: 12260,ppid: 5899
  25. I am a process!,pid: 12260,ppid: 5899
  26. I am a process!,pid: 12260,ppid: 5899
  27. I am a process!,pid: 12260,ppid: 5899
  28. ...
  29. ...
  30. //新建会话1:
  31. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  32. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  33. 5899 12260 12260 5899 pts/ 0 12260 S+ 1002 0: 00 ./mytest
  34. [HJM@hjmlcc ~]$
  35. //先把本次有关可执行程序mytest所形成的进程结束掉,然后再重新启动有关可执行程序mytest所形成的
  36. //进程:
  37. //新建会话0:
  38. [HJM@hjmlcc ~]$ ls
  39. Makefile mytest mytest.c
  40. [HJM@hjmlcc ~]$ ./mytest
  41. //有关可执行程序mytest所形成的进程的进程ID(PID)为13359,而该进程的父进程ID(PPID)为5899、
  42. I am a process!,pid: 13359,ppid: 5899
  43. I am a process!,pid: 13359,ppid: 5899
  44. I am a process!,pid: 13359,ppid: 5899
  45. I am a process!,pid: 13359,ppid: 5899
  46. ...
  47. ...
  48. //新建会话1:
  49. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  50. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  51. 5899 13359 13359 5899 pts/ 0 13359 S+ 1002 0: 00 ./mytest
  52. [HJM@hjmlcc ~]$
  53. //由上可知,当我们每一次结束掉上一次有关可执行程序mytest所形成的进程,然后再重新启动有关可执行
  54. //程序mytest所形成的进程时,会发现,这多个由有关可执行程序mytest所形成的进程中的进程ID(PID)都
  55. //不相同,但是这多个由有关可执行程序mytest所形成的进程中的父进程ID(PPID)则都相同、
  56. //不管有关可执行程序mytest所形成的进程是否正在运行(时实启动),而该进程的父进程则都是一直正在
  57. //运行(时实启动)的、
  58. //新建会话0:
  59. [HJM@hjmlcc ~]$ ls
  60. Makefile mytest mytest.c
  61. [HJM@hjmlcc ~]$ ./mytest
  62. I am a process!,pid: 15708,ppid: 5899
  63. I am a process!,pid: 15708,ppid: 5899
  64. I am a process!,pid: 15708,ppid: 5899
  65. ...
  66. ...
  67. //新建会话1:
  68. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 5899
  69. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  70. 5898 5899 5899 5899 pts/ 0 15708 Ss 1002 0: 00 -bash
  71. //上述进程的进程ID(PID)为5899,这也就是有关可执行程序mytest所形成的进程的父进程、
  72. //几乎我们在命令行上所执行的所有的指令,包括运行我们自己编写的程序代码所形成的可执行程序,所形
  73. //成的进程都是bash进程的子进程、
  74. 5899 15708 15708 5899 pts/ 0 15708 S+ 1002 0: 00 ./mytest
  75. 8631 16126 16125 8631 pts/ 1 16125 S+ 1002 0: 00 grep --color=auto5899
  76. [HJM@hjmlcc ~]$

bash 进程和 init 进程:
    bash 进程就是我们每打开一个终端后运行的第一个程序,他会捕捉你的键盘输入,看你输入了什么指令,则会解析执行对应的指令程序,在终端中运行的执行程序所对应进程默认父进程就是这个 bash 进程( 因为这些指令程序对应的进程都是这个 bash 进程创建的 )
    init 进程( 也叫1号进程,就是操作系统 )是系统内非常 重要的一个管理进程,系统中只有一个这个进程( bash 进程是打开了多少终端就会运行多少个 ),进程 PID 为1、


3.7、通过系统调用接口创建子进程 - fork 初识

    创建(启动)进程有很多方法,除了我们知道的运行可执行程序从而创建(启动)一个进程之外,还可以使用 Linux 操作系统所提供的系统调用接口 fork 直接创建(启动)某一个进程的子进程、        


  
  1. [HJM@hjmlcc ~]$ man 2 fork
  2. //如果成功创建(启动)了当前进程的子进程,则会把当前进程的子进程的PID的值返回给当前进程(父进程)
  3. //的id变量中,把0返回给当前进程的子进程的id变量中,因此,此时的Linux操作系统所提供的系统调用接
  4. //口fork有两个返回值、
  5. //这里是查询Linux操作系统提供的系统调用接口,在本质上,fork也是一个函数,如上,他有两个返回值,在
  6. //之前我们都没有遇到过、
  7. FORK( 2) Linux Programmer ' s Manual FORK(2)
  8. NAME
  9. fork - create a child process
  10. SYNOPSIS
  11. #include <unistd.h>
  12. pid_t fork(void);
  13. DESCRIPTION
  14. fork() creates a new process by duplicating the calling process.
  15. The new process, referred to as the child, is an exact duplicate
  16. of the calling process, referred to as the parent, except for the
  17. following points:
  18. * The child has its own unique process ID, and this PID does not
  19. match the ID of any existing process group (setpgid(2)).
  20. * The child's parent process ID is the same as the parent's
  21. process ID.
  22. * The child does not inherit its parent's memory locks (mlock(2),
  23. mlockall(2)).
  24. * Process resource utilizations (getrusage(2)) and CPU time coun‐
  25. ters (times(2)) are reset to zero in the child.
  26. * The child's set of pending signals is initially empty (sigpend‐
  27. ing(2)).
  28. * The child does not inherit semaphore adjustments from its par‐
  29. ent (semop(2)).
  30. * The child does not inherit record locks from its parent
  31. (fcntl(2)).
  32. Manual page fork(2) line 1 (press h for help or q to quit)/return val
  33. RETURN VALUE
  34. On success, the PID of the child process is returned in the par‐
  35. ent, and 0 is returned in the child. On failure, -1 is returned
  36. in the parent, no child process is created, and errno is set
  37. appropriately.
  38. //如果成功创建(启动)了当前进程的子进程,则会把当前进程的子进程的PID的值返回给当前进程(父进程)
  39. //的id变量中,把0返回给当前进程的子进程的id变量中,如果没有成功,则会把-1返回给当前进程(父进程)
  40. //的id变量中,此时并没有成功创建(启动)当前进程的子进程、
  41. ERRORS
  42. EAGAIN fork() cannot allocate sufficient memory to copy the par‐
  43. ent's page tables and allocate a task structure for the
  44. child.
  45. EAGAIN It was not possible to create a new process because the
  46. caller's RLIMIT_NPROC resource limit was encountered. To
  47. exceed this limit, the process must have either the
  48. CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.
  49. ENOMEM fork() failed to allocate the necessary kernel structures
  50. because memory is tight.
  51. ENOSYS fork() is not supported on this platform (for example,
  52. hardware without a Memory-Management Unit).
  53. CONFORMING TO
  54. SVr4, 4.3BSD, POSIX.1-2001.
  55. NOTES
  56. Under Linux, fork() is implemented using copy-on-write pages, so
  57. the only penalty that it incurs is the time and memory required to
  58. duplicate the parent's page tables, and to create a unique task
  59. structure for the child.
  60. Since version 2.3.3, rather than invoking the kernel's fork() sys‐
  61. tem call, the glibc fork() wrapper that is provided as part of the
  62. NPTL threading implementation invokes clone(2) with flags that
  63. provide the same effect as the traditional system call. (A call
  64. to fork() is equivalent to a call to clone(2) specifying flags as
  65. Manual page fork(2) line 101/154 89% (press h for help or q to quit)q

  
  1. [HJM@hjmlcc ~]$ ls
  2. Makefile mytest.c
  3. [HJM@hjmlcc ~]$ cat mytest.c
  4. #include<stdio.h>
  5. #include<unistd.h>
  6. int main()
  7. {
  8. pid_t id = fork();
  9. printf( "hello,lcc\n");
  10. sleep( 1);
  11. return 0;
  12. }
  13. [HJM@hjmlcc ~]$ make
  14. gcc mytest.c -o mytest
  15. [HJM@hjmlcc ~]$ ls
  16. Makefile mytest mytest.c
  17. [HJM@hjmlcc ~]$ ./mytest
  18. hello,lcc
  19. hello,lcc
  20. [HJM@hjmlcc ~]$ //打印了两次、
  21. //这是因为:父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口fork调用处之后的所有
  22. //代码和该系统调用接口 fork 函数体内部的所有的代码、
  23. //例子:
  24. [HJM@hjmlcc ~]$ ls
  25. lcc.c Makefile mytest.c
  26. [HJM@hjmlcc ~]$ cat lcc.c
  27. #include<stdio.h>
  28. #include<unistd.h>
  29. int main()
  30. {
  31. printf( "321\n");
  32. pid_t id = fork();
  33. printf( "123\n");
  34. return 0;
  35. }
  36. [HJM@hjmlcc ~]$ gcc lcc.c
  37. [HJM@hjmlcc ~]$ ls
  38. a.out lcc.c Makefile mytest.c
  39. [HJM@hjmlcc ~]$ ./a.out
  40. 321
  41. 123
  42. 123
  43. [HJM@hjmlcc ~]$

  
  1. [HJM@hjmlcc ~]$ ls
  2. Makefile mytest.c
  3. [HJM@hjmlcc ~]$ cat mytest.c
  4. #include<stdio.h>
  5. #include<unistd.h>
  6. int main()
  7. {
  8. pid_t id = fork();
  9. printf( "hello,lcc!id:%d\n",id);
  10. sleep( 1);
  11. return 0;
  12. }
  13. [HJM@hjmlcc ~]$ ls
  14. Makefile mytest.c
  15. [HJM@hjmlcc ~]$ make
  16. gcc mytest.c -o mytest
  17. [HJM@hjmlcc ~]$ ls
  18. Makefile mytest mytest.c
  19. [HJM@hjmlcc ~]$ ./mytest
  20. hello,lcc!id: 23465
  21. hello,lcc!id: 0
  22. [HJM@hjmlcc ~]$ ./mytest
  23. hello,lcc!id: 23812
  24. hello,lcc!id: 0
  25. [HJM@hjmlcc ~]$ ./mytest
  26. hello,lcc!id: 23832
  27. hello,lcc!id: 0
  28. [HJM@hjmlcc ~]$
  29. //上述现象在讲解进程地址空间时再进行阐述、
  30. //新建会话0:
  31. [HJM@hjmlcc ~]$ ls
  32. Makefile mytest.c
  33. [HJM@hjmlcc ~]$ cat mytest.c
  34. #include<stdio.h>
  35. #include<unistd.h>
  36. int main()
  37. {
  38. pid_t id = fork();
  39. if(id == 0)
  40. {
  41. //当前进程(父进程)的子进程、
  42. while( 1)
  43. {
  44. printf( "我是子进程!,我的进程ID(PID)是:%d,我的父进程ID(PPID)是:%d\n",getpi
  45. sleep( 1);
  46. }
  47. }
  48. else{
  49. //当前进程(父进程)、
  50. while( 1)
  51. {
  52. printf( "我是父进程!,我的进程ID(PID)是:%d,我的父进程ID(PPID)是:%d\n",getpi
  53. sleep( 1);
  54. }
  55. }
  56. return 0;
  57. }
  58. //在C语言中,if和else不可以同时执行,且在C语言中没有可能同时存在两个或两个以上的死循环、
  59. [HJM@hjmlcc ~]$ make
  60. gcc mytest.c -o mytest
  61. [HJM@hjmlcc ~]$ ls
  62. Makefile mytest mytest.c
  63. [HJM@hjmlcc ~]$ ./mytest
  64. 我是父进程!,我的进程 ID(PID)是: 19571,我的父进程 ID(PPID)是: 5899
  65. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  66. 我是父进程!,我的进程 ID(PID)是: 19571,我的父进程 ID(PPID)是: 5899
  67. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  68. 我是父进程!,我的进程 ID(PID)是: 19571,我的父进程 ID(PPID)是: 5899
  69. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  70. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  71. 我是父进程!,我的进程 ID(PID)是: 19571,我的父进程 ID(PPID)是: 5899
  72. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  73. 我是父进程!,我的进程 ID(PID)是: 19571,我的父进程 ID(PPID)是: 5899
  74. 我是子进程!,我的进程 ID(PID)是: 19572,我的父进程 ID(PPID)是: 19571
  75. ...
  76. ...
  77. //新建会话1:
  78. [HJM@hjmlcc ~]$ ls
  79. Makefile mytest mytest.c
  80. [HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
  81. PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  82. 5899 19571 19571 5899 pts/ 0 19571 S+ 1002 0: 00 ./mytest
  83. 19571 19572 19571 5899 pts/ 0 19571 S+ 1002 0: 00 ./mytest
  84. [HJM@hjmlcc ~]$
  85. //1、
  86. //这是因为:父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口fork调用处之后的所有
  87. //代码和该系统调用接口 fork 函数体内部的所有的代码、
  88. //2、
  89. //父进程和子进程各自的id变量中的值不同,在调用Linux操作系统所提供的系统调用接口fork之后,可以
  90. //通过父进程和子进程中各自不同的id变量中的值进行判断,让父进程和子进程分别执行不同的代码块、

补充一:

    在 Linux 操作系统所提供的系统调用接口 fork 中,当成功创建(启动)某一个进程的子进程时,为什么会把当前进程的子进程的 PID 的值返回给当前进程(父进程)的 id 变量中,把 0 返回给当前进程的子进程的 id 变量中呢?

    创建(启动)某一个进程的子进程本质上就是相当于在操作系统中多一个执行流来帮助我们完成一部分代码,这就叫做多进程代码,父进程比子进程一定是1 :n( n>=1,能够称其为父进程,则它至少有一个子进程 ),但是任意一个子进程有且仅有一个父进程,因此,父进程必须要有标识子进程的方案,这个方案就是当成功创建(启动)某一个进程的子进程时,把当前进程的子进程的 PID 的值返回给当前进程(父进程)的 id 变量中,而把 0 返回给当前进程的子进程的 id 变量中是因为,子进程最重要的是要知道自己被创建成功了,任意一个子进程有且仅有一个父进程,因此子进程寻找父进程的成本非常低,只需要使用 Linux 操作系统所提供的系统调用接口 getppid 即可,所以,只需要把 0 返回给当前进程的子进程的 id 变量中即可、


补充二:

    在 Linux 操作系统所提供的系统调用接口 fork 的函数体中,当成功创建(启动)某一个进程的子进程时,为什么会进行两次返回操作 ?

    子进程所有的属性数据信息,大部分(基本上,比如优先级,状态等等,具体有哪些会在后期再进行具体的阐述)都是从该子进程的父进程继承(拷贝)得到的,但并不都是从该子进程的父进程继承(拷贝)得到的,比如:该子进程的进程 ID(PID) 等,就不是从该子进程的父进程继承(拷贝)得到的、

    子进程被创建(启动)出来就是为了执行代码,计算数据的,那么该子进程的代码从哪里来的呢 ?,答:没有地方来,子进程只能与其父进程执行一样的代码,我们所谓的:父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口 fork 调用处之后的所有的代码和该系统调用接口 fork 函数体内部的所有的代码,在此,本质上,子进程共享并执行 Linux 操作系统所提供的系统调用接口 fork 调用处之后的所有的代码和该系统调用接口 fork 函数体内部的所有的代码都是属于其父进程的代码,注意:父进程与子进程两者的数据(全局变量,静态变量等等数据)要各自独立开来,因为进程具有独立性,父子进程的数据必须是独立分开的,在后期讲解写时拷贝时再进行具体阐述,虽然父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口 fork 调用处之后的所有代码和该系统调用接口 fork 函数体内部的所有的代码,但是常规情况下,可以通过父进程和子进程各自的 id 变量中的值不同,在调用 Linux 操作系统所提供的系统调用接口 fork 之后,可以通过父进程和子进程中各自不同的 id 变量中的值进行判断,让父进程和子进程分别执行不同的代码块、

    调用一个函数,当在这个函数的函数体中准备 return 时,此时该函数的主题,核心功能已经完成了,此处的 return ,并不是核心逻辑的一部分,这就意味着,当在 Linux 操作系统所提供的系统调用接口 fork 的函数体中,在执行 return 代码(语句)之前,其当前进程的子进程就已经被创建(启动)好了、

    如何理解进程被运行?,我们知道,进程等于加载到内存中的可执行程序(代码及数据)加上该进程对应的内核数据结构( 该进程对应的描述该进程所使用的 struct 结构体(task_struct) ),但是并不代表描述某一个进程所使用的 struct 结构体只能在一个双链表(或其它高效的数据结构,但此处主要是指双链表)中,也可以同时放在另外一个双链表(或其它高效的数据结构,但此处主要是指双链表)中,其次,在操作系统内部存在一个我们称为调度器的代码模块、

    在 Linux 内核中的每一个 CPU 中,都会存在一个叫做运行队列( runqueue )的东西,运行队列中所放的都是进程,所谓的调度器调度,就是让该运行队列中的每一个进程根据他们的优先级(使用队列就已经明确了优先级的问题)去被 CPU 运行,当某一个进程被调度,也就是被 CPU 运行时,本质上就是让 CPU 找到该进程对应的可执行程序(代码和数据),通过找到的代码去访问它的数据,这样就是运行了该进程,还要注意,我们所谓的创建(启动)某一个进程的子进程,该子进程还需要被 CPU 运行,还需要把该子进程放到运行队列中,以此供 CPU去调度,该子进程的可执行程序(代码和数据,此处所谓的数据是该子进程独立的数据,而此处所谓的代码指的就是该子进程的父进程的代码),由上述可知,在 Linux 操作系统所提供的系统调用接口 fork 的函数体中,当在执行 return 代码(语句)之前,其当前进程的子进程就已经被创建(启动)好了,即:在 Linux 操作系统所提供的系统调用接口 fork 的函数体中,在执行 return 代码(语句)之前,就已经存在了父进程和子进程,并且此时,父进程和子进程都已经放在了运行队列中,父进程和子进程都有可能随时被 CPU 调度,当两者都被 CPU 调度时,父进程和子进程共享且都会执行 Linux 操作系统所提供的系统调用接口 fork 调用处之后的所有代码和该系统调用接口 fork 函数体内部的所有的代码,所以此处就都会执行 Linux 操作系统所提供的系统调用接口 fork 的函数体中的 return代码(程序),因此,在 Linux 操作系统所提供的系统调用接口 fork 的函数体中进行两次返回操作,且有对应的两个返回值、

拓展:

    我们在写 C 代码时所使用的变量,有可能并不是存在于内存中,实际上,这一个变量名最后会对应到不同的存储空间中,在讲解地址空间时再进行具体的阐述、


转载:https://blog.csdn.net/lcc11223/article/details/127800569
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场