< Linux >:Linux 进程概念 (2)

目录

3.5、查看进程

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

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


3.5、查看进程

[HJM@hjmlcc ~]$ clear
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ ls
[HJM@hjmlcc ~]$ touch mytest.c
[HJM@hjmlcc ~]$ ls
mytest.c
[HJM@hjmlcc ~]$ touch Makefile
[HJM@hjmlcc ~]$ ls
Makefile  mytest.c
[HJM@hjmlcc ~]$ vim Makefile
[HJM@hjmlcc ~]$ cat Makefile
mytest:mytest.c
	gcc mytest.c -o mytest

.PHONY:clean
clean:
	rm -f mytest
[HJM@hjmlcc ~]$ vim mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  while(1)        //死循环、
  {
    printf("I am a process!\n");
    sleep(1);
  }
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
//此处的 mytest 是可执行程序,是一个普通文件,存在于磁盘上,该磁盘指的并不是在我们笔记本中的磁
//盘上,而是存在于云服务器上的磁盘中、
[HJM@hjmlcc ~]$ ldd mytest
	linux-vdso.so.1 =>  (0x00007ffcba19d000)
	/$LIB/libonion.so => /lib64/libonion.so (0x00007f18b638f000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f18b5ea8000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f18b5ca4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f18b6276000)
[HJM@hjmlcc ~]$ file mytest
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
[HJM@hjmlcc ~]$ ./mytest   
//之前我们称上述操作为将可执行程序mytest运行起来,现在通过上述操作便可形成一个进程,因此我们可
//以称上述操作是:一个关于可执行程序mytest所形成的进程、
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
...
...

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

方法一:

[HJM@hjmlcc ~]$ clear
[HJM@hjmlcc ~]$ ps ajx   //a:all,j:job,x:以特定格式进行显示,或者是: ps axj ,顺序无所谓、
//把 Linux 操作系统中所有的正在运行的时实启动的进程及其信息全部显示出来、
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0  17:46 /usr/lib/sys
    0     2     0     0 ?           -1 S        0   0:03 [kthreadd]
    2     4     0     0 ?           -1 S<       0   0:00 [kworker/0:0
    2    18     0     0 ?           -1 S        0   0:00 [kdevtmpfs]
    2    19     0     0 ?           -1 S<       0   0:00 [netns]
    2    20     0     0 ?           -1 S        0   0:02 [khungtaskd]
...
...
    2 30148     0     0 ?           -1 S        0   0:00 [kworker/0:1
    1 30373 30373 30373 ?           -1 Ssl   1002   0:00 /home/HJM/.V
    1 30380 30380 30380 ?           -1 Ssl   1002   0:00 /home/HJM/.V
30380 30391 30380 30380 ?           -1 Z     1002   0:00 [querydb] <d
    1 31068 31068 31068 ?           -1 Ssl   1002   0:00 /home/HJM/.V
    1 31076 31076 31076 ?           -1 Ssl   1002   0:00 /home/HJM/.V
31076 31087 31076 31076 ?           -1 Z     1002   0:00 [querydb] <d
    2 31438     0     0 ?           -1 S        0   0:00 [kworker/0:3
    2 32544     0     0 ?           -1 S        0   0:01 [kworker/0:0
[HJM@hjmlcc ~]$ ps ajx | grep 'mytest'
10484 12399 12399 10484 pts/0    12399 S+    1002   0:00 ./mytest
12404 13061 13060 12404 pts/1    13060 S+    1002   0:00 grep --color=automytest
//在Linux操作系统中所有的正在运行的时实启动的进程及其信息中查找关于可执行程序mytest所形成的
//进程及其信息,若关于可执行程序mytest所形成的进程正在运行或时实启动,则会把关于可执行程序mytes
//t所形成的进程及其信息显式出来,若关于可执行程序mytest所形成的进程未正在运行或未时实启动,则
//不会把关于可执行程序mytest所形成的进程及其信息显式出来、

//对于上述指令行而言,有关可执行程序ps所形成的进程和有关可执行程序grep所形成的进程一直都是在
//运行(时实启动)的,有关可执行程序mytest所形成的进程可能正在运行(时实启动),也有可能没有正在运
//行(时实启动),由于上面是对有关可执行程序mytest形成的进程及其信息进行的搜索,按理说只需要显式
//出来有关可执行程序mytest形成的进程是否正在运行(时实启动)即可,但此处还把正在运行(时实启动)
//的有关可执行程序grep所形成的进程及其信息显示了出来,其次,虽然这里并未显式出来正在运行(时实
//启动的)有关可执行程序ps所形成的进程及其信息,但要知道,有关可执行程序ps所形成的进程一直正在
//运行(时实启动),只不过这里并没有把该进程及其信息显式出来而已,由于此处还默认显式出来正在运行
//(时实启动的)有关可执行程序grep所形成的进程及其信息,若不想显式该进程及其信息的话,可以通过下
//述操作:
[HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
//即:上述操作中grep -v的后面只要匹配到某一个有关某一个可执行程序所形成的进程所对应的可执行程
//序的名字,则该进程及其信息一律不进行显式,此时我们知道,对于有关可执行程序grep所形成的进程而
//言是一直在运行(时实启动)的,按理说在下面会显示出来该进程及其信息,但是,上述操作中又有grep -v
// grep,所以在下面结果中就不再进行显示该进程及其信息了、
10484 23680 23680 10484 pts/0    23680 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ 

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

[HJM@hjmlcc ~]$ ls /usr/bin/*
//usr:用户,bin:二进制、
/usr/bin/[
/usr/bin/a2p
/usr/bin/abrt-action-analyze-backtrace
/usr/bin/abrt-action-analyze-c
/usr/bin/abrt-action-analyze-ccpp-local
/usr/bin/abrt-action-analyze-core
/usr/bin/abrt-action-analyze-oops
/usr/bin/abrt-action-analyze-python
/usr/bin/abrt-action-analyze-vmcore
/usr/bin/abrt-action-analyze-vulnerability
/usr/bin/abrt-action-analyze-xorg
/usr/bin/abrt-action-check-oops-for-hw-err
...
...
/usr/bin/zip
/usr/bin/zipcloak
/usr/bin/zipgrep
/usr/bin/zipinfo
/usr/bin/zipnote
/usr/bin/zipsplit
/usr/bin/zless
/usr/bin/zmore
/usr/bin/znew
/usr/bin/zsoelim
[HJM@hjmlcc ~]$ 

//之前我们执行的所有的指令,本质上都是在运行可执行程序,则都会形成这些可执行程序对应的进程,只不
//过像:ls,pwd等等这些指令,在执行时,也相当于在运行可执行程序,因此则都会形成他们对应的进程,但
//是他们对应的进程的生命周期很短就结束了,即当我执行完这些指令时,由这些指令所形成的进程很快就
//结束了,在我通过方法查看正在运行或时实启动的进程及其信息之前,由这些指令所形成的进程就已经结
//束了,所以当在查看正在运行或时实启动的进程及其信息时,就看不到由这些指令所形成的进程及其信
//息了、

//在 Windows 系统中,当我们双击 CF 的快捷方式,而该快捷方式指向了 CF 的可执行程序,所以就相当
//于在双击 CF 的可执行程序,即就相当于在运行 CF 的可执行程序,因此便形成了一个与它对应的进程,
//就可以愉快的玩游戏了、

方法二:

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

[HJM@hjmlcc ~]$ ps ajx | grep 'mytest'
12404  3406  3405 12404 pts/1     3405 S+    1002   0:00 grep --color=auto mytest
10484 31395 31395 10484 pts/0    31395 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
10484 31395 31395 10484 pts/0    31395 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ ps ajx | head -1       //是1不是l,代表前1行、
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
[HJM@hjmlcc ~]$ ps ajx | head -5
//把 Linux 操作系统中所有的正在运行的时实启动的进程及其信息的前 5 行全部显示出来,其中第一行
//代表进程属性的名称、
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0  17:59 /usr/lib/systemd/systemd --system --deserialize 23
    0     2     0     0 ?           -1 S        0   0:03 [kthreadd]
    2     4     0     0 ?           -1 S<       0   0:00 [kworker/0:0H]
    2     6     0     0 ?           -1 S        0   2:20 [ksoftirqd/0]
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
//当指令行:ps ajx | head -1执行成功后,再执行指令行:head -1 && ps ajx | grep 'mytest' | grep
// -v grep,若前面的指令行执行失败,则后面的指令行就不再进行执行了、
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10484 31395 31395 10484 pts/0    31395 S+    1002   0:00 ./mytest
//由此可知,有关可执行程序mytest所形成的进程的 PID 是31395、
[HJM@hjmlcc ~]$ ls /proc/31395
attr        cmdline          environ  io         mem         ns             pagemap      sched      stack    task
autogroup   comm             exe      limits     mountinfo   numa_maps      patch_state  schedstat  stat     timers
auxv        coredump_filter  fd       loginuid   mounts      oom_adj        personality  sessionid  statm    uid_map
cgroup      cpuset           fdinfo   map_files  mountstats  oom_score      projid_map   setgroups  status   wchan
clear_refs  cwd              gid_map  maps       net         oom_score_adj  root         smaps      syscall
[HJM@hjmlcc ~]$ ls /proc/31395 -d
/proc/31395

//此时如果把有关可执行程序mytest所形成的进程结束掉,然后再执行指令:ls /proc/31395 -d时,得到
//如下结果,这是因为,根目录下的proc目录中存放的是当前 Linux 操作系统中正在运行或时实启动的进
//程及其信息、
[HJM@hjmlcc ~]$ ls /proc/31395 -d
ls: cannot access /proc/31395: No such file or directory
[HJM@hjmlcc ~]$ 

//当把有关可执行程序mytest所形成的进程再次启动时,若再执行上述指令:ls /proc/31395 -d,会发现
//得到的结果是:ls: cannot access /proc/31395: No such file or directory,如下所示:
[HJM@hjmlcc ~]$ ls /proc/31395 -d
ls: cannot access /proc/31395: No such file or directory
[HJM@hjmlcc ~]$ ps ajx | grep 'mytest' | grep -v grep
10484 27073 27073 10484 pts/0    27073 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10484 27073 27073 10484 pts/0    27073 S+    1002   0:00 ./mytest
//这是因为:当我们重新启动有关可执行程序mytest所形成的进程时,此次的该进程与前一次启动有关可执行
//程序mytest所形成的进程并不是同一个进程,后者相对于前者而言是一个新的进程,所以此次的有关可执
//行程序mytest所形成的进程的 PID 也会发生改变,Linux 操作系统会为其重新分配 PID ,由31395变成
//了27073、
[HJM@hjmlcc ~]$ ls /proc/27073 -d
/proc/27073
[HJM@hjmlcc ~]$ ls /proc/27073
//以下则是有关可执行程序mytest所形成的进程的所有的属性数据信息的集合,时实的以文件的方式进行
//显示、
attr        cmdline          environ  io         mem         ns             pagemap      sched      stack    task
autogroup   comm             exe      limits     mountinfo   numa_maps      patch_state  schedstat  stat     timers
auxv        coredump_filter  fd       loginuid   mounts      oom_adj        personality  sessionid  statm    uid_map
cgroup      cpuset           fdinfo   map_files  mountstats  oom_score      projid_map   setgroups  status   wchan
clear_refs  cwd              gid_map  maps       net         oom_score_adj  root         smaps      syscall
[HJM@hjmlcc ~]$ ls /proc/27073 -al
total 0
dr-xr-xr-x   9 HJM  HJM  0 Nov 12 19:09 .
dr-xr-xr-x 124 root root 0 Jul 28 11:13 ..
dr-xr-xr-x   2 HJM  HJM  0 Nov 12 19:15 attr
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:15 autogroup
-r--------   1 HJM  HJM  0 Nov 12 19:15 auxv
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 cgroup
--w-------   1 HJM  HJM  0 Nov 12 19:15 clear_refs
-r--r--r--   1 HJM  HJM  0 Nov 12 19:09 cmdline
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:15 comm
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:15 coredump_filter
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 cpuset
lrwxrwxrwx   1 HJM  HJM  0 Nov 12 19:09 cwd -> /home/HJM
//上述代表有关可执行程序mytest所形成的的进程当前的工作路径、
-r--------   1 HJM  HJM  0 Nov 12 19:09 environ
lrwxrwxrwx   1 HJM  HJM  0 Nov 12 19:09 exe -> /home/HJM/mytest
//上述代表的就是有关可执行程序mytest所形成的的进程对应的在云服务器中的磁盘中的可执行程序mytes
//t所在的路径、
...
...
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 statm
-r--r--r--   1 HJM  HJM  0 Nov 12 19:09 status
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 syscall
dr-xr-xr-x   3 HJM  HJM  0 Nov 12 19:15 task
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 timers
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:15 uid_map
-r--r--r--   1 HJM  HJM  0 Nov 12 19:15 wchan
[HJM@hjmlcc ~]$ 

//进程的 PID 以及当前路径等等都属于进程的属性数据信息,都属于系统数据,都在描述该进程的进程控
//制块(PCB),在 Linux 系统下的 task_struct 结构体中、

//在之前,我们认为当前路径就是程序或者源代码所在的路径,其实本质上并不准确,真正意义上的当前路径
//指的就是:进程当前所在(工作)的路径,当进程启动时,这个路径由进程自己进行维护、

//如下所示:    
//新建会话0:
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  FILE* fp=fopen("log.txt","w");
  //由此可知,log.txt前面并没有指定路径,则默认为当前路径下,如果在当前路径下不存在普通文
  //件log.txt,则会新建一个名为log.txt的普通文件、
  while(1)
  {
    printf("I am a process!\n");
    sleep(1);
  }
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ mv mytest code  
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
mytest
[HJM@hjmlcc code]$ ./mytest
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
...
...


//新建会话1:
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
mytest
[HJM@hjmlcc code]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10484  1738  1738 10484 pts/0     1738 S+    1002   0:00 ./mytest
[HJM@hjmlcc code]$ ls /proc/1738
attr             environ    mem            pagemap      stack
autogroup        exe        mountinfo      patch_state  stat
auxv             fd         mounts         personality  statm
cgroup           fdinfo     mountstats     projid_map   status
clear_refs       gid_map    net            root         syscall
cmdline          io         ns             sched        task
comm             limits     numa_maps      schedstat    timers
coredump_filter  loginuid   oom_adj        sessionid    uid_map
cpuset           map_files  oom_score      setgroups    wchan
cwd              maps       oom_score_adj  smaps
[HJM@hjmlcc code]$ ls /proc/1738 -d
/proc/1738
[HJM@hjmlcc code]$ ls /proc/1738 -al
total 0
dr-xr-xr-x   9 HJM  HJM  0 Nov 12 19:44 .
dr-xr-xr-x 126 root root 0 Jul 28 11:13 ..
dr-xr-xr-x   2 HJM  HJM  0 Nov 12 19:45 attrer
-r--r--r--   1 HJM  HJM  0 Nov 12 19:45 cpuset
lrwxrwxrwx   1 HJM  HJM  0 Nov 12 19:44 cwd -> /home/HJM/code         //当前路径、
-r--------   1 HJM  HJM  0 Nov 12 19:45 environ
lrwxrwxrwx   1 HJM  HJM  0 Nov 12 19:44 exe -> /home/HJM/code/mytest
lrwxrwxrwx   1 HJM  HJM  0 Nov 12 19:44 root -> /
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:45 sched
...
...
-r--r--r--   1 HJM  HJM  0 Nov 12 19:45 syscall
dr-xr-xr-x   3 HJM  HJM  0 Nov 12 19:45 task
-r--r--r--   1 HJM  HJM  0 Nov 12 19:45 timers
-rw-r--r--   1 HJM  HJM  0 Nov 12 19:45 uid_map
-r--r--r--   1 HJM  HJM  0 Nov 12 19:45 wchan
[HJM@hjmlcc ~]$ 


//新建会话0:
...
...
I am a process!
I am a process!
I am a process!
I am a process!
I am a process!
^C
[HJM@hjmlcc code]$ ls
log.txt  mytest




//注意:
//1、
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
[HJM@hjmlcc code]$ cd ..
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ make clean
rm -f mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ 


//2、
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
[HJM@hjmlcc code]$ cd ..
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ mv mytest code
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
mytest
[HJM@hjmlcc code]$ make clean
make: *** No rule to make target `clean'.  Stop.   //无法删除可执行程序mytest、
[HJM@hjmlcc code]$ cd ..
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ make clean
rm -f mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ cd code
[HJM@hjmlcc code]$ ls
mytest                           //仍没有删除掉可执行程序mytest、
[HJM@hjmlcc code]$ 
//在讲解粘滞位时,tmp目录文件是一个共享的目录文件,里面存放的是临时文件、
//proc目录文件是 Linux 系统根目录下的一个目录,proc:process,proc:内存文件系统,该目录文件中存
//放的是当前操作系统中正在运行或时实运行的进程及其信息、
[HJM@hjmlcc ~]$ ls /
bin  boot  data  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[HJM@hjmlcc ~]$ 

[HJM@hjmlcc ~]$ ls /
bin  boot  data  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[HJM@hjmlcc ~]$ ls /proc
1      12535  16515  20344  25287  28     31335  50    7          cpuinfo      irq         modules       swaps
10     13     16526  20730  255    29     31368  51    8          crypto       kallsyms    mounts        sys
10470  1389   16792  20827  256    290    36     52    8227       devices      kcore       mtrr          sysrq-trigger
10483  1390   18     21     26     291    37     577   9          diskstats    keys        net           sysvipc
10484  14     18820  21813  262    292    3756   6     925        dma          key-users   pagetypeinfo  timer_list
11     1521   18853  22     266    29633  38     646   991        driver       kmsg        partitions    timer_stats
1164   1552   19     23     267    30123  387    648   993        execdomains  kpagecount  sched_debug   tty
1178   1558   19039  24     269    30373  3871   65    acpi       fb           kpageflags  schedstat     uptime
12     1559   19089  24315  27     30380  39     651   buddyinfo  filesystems  loadavg     scsi          version
1207   1575   197    2472   270    30391  4      6515  bus        fs           locks       self          vmallocinfo
1222   16     2      2485   27176  31068  407    652   cgroups    interrupts   mdstat      slabinfo      vmstat
12404  160    20     2496   27184  31076  47     654   cmdline    iomem        meminfo     softirqs      xpmem
12524  16503  20337  25     27195  31087  49     659   consoles   ioports      misc        stat          zoneinfo
[HJM@hjmlcc ~]$ ls /proc -l
total 0
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 1
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 10
dr-xr-xr-x  9 root           root                         0 Nov 12 14:59 10470
dr-xr-xr-x  9 HJM            HJM                          0 Nov 12 14:59 10483
dr-xr-xr-x  9 HJM            HJM                          0 Nov 12 14:59 10484
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 11
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 1164
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 1178
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 12
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 1207
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 8
dr-xr-xr-x  9 root           root                         0 Nov 12 14:48 8227
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 9
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 925
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 991
dr-xr-xr-x  9 root           root                         0 Jul 28 11:13 993
dr-xr-xr-x  2 root           root                         0 Nov 12 16:47 acpi
-r--r--r--  1 root           root                         0 Nov 12 16:47 buddyinfo
dr-xr-xr-x  4 root           root                         0 Nov 12 16:47 bus
-r--r--r--  1 root           root                         0 Nov 12 16:47 cgroups
-r--r--r--  1 root           root                         0 Nov 12 16:47 cmdline
-r--r--r--  1 root           root                         0 Nov 12 16:47 consoles
-r--r--r--  1 root           root                         0 Nov 12 16:47 cpuinfo
-r--r--r--  1 root           root                         0 Nov 12 16:47 crypto
-r--r--r--  1 root           root                         0 Nov 12 16:47 devices
...
...
-r--r--r--  1 root           root                         0 Nov 12 16:47 version
-r--------  1 root           root                         0 Nov 12 16:47 vmallocinfo
-r--r--r--  1 root           root                         0 Nov 12 16:47 vmstat
dr-xr-xr-x  2 root           root                         0 Nov 12 16:47 xpmem
-r--r--r--  1 root           root                         0 Nov 12 16:47 zoneinfo
[HJM@hjmlcc ~]$ 

 方法三:

//一、
//新建会话0:
[HJM@hjmlcc ~]$ ls
a.out  lcc.c  Makefile  process  process.c
[HJM@hjmlcc ~]$ ./process
I am a process:9684
I am a process:9684
I am a process:9684
I am a process:9684
I am a process:9684
...
...


//新建会话1:                                      //a,u,x三者的顺序无所谓、
[HJM@hjmlcc ~]$ ls
a.out  lcc.c  Makefile  process  process.c
[HJM@hjmlcc ~]$ ps aux | head -1 && ps aux | grep 'process' | grep -v grep
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
HJM       9684  0.0  0.0   7332   380 pts/0    S+   17:31   0:00 ./process
[HJM@hjmlcc ~]$              



//2、
//新建会话0:
...
...
I am a process:9684
I am a process:9684
I am a process:9684
I am a process:9684
^C
[HJM@hjmlcc ~]$ 


//新建会话1:
[HJM@hjmlcc ~]$ ls
a.out  lcc.c  Makefile  process  process.c
[HJM@hjmlcc ~]$ ps aux | head -1 && ps aux | grep 'process' | grep -v grep
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
[HJM@hjmlcc ~]$ 

拓展:

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

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

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

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

//当启动一个进程,则该进程就是正在运行(时实启动)的,则操作系统会为该进程分配一个 PID 、
[HJM@hjmlcc ~]$ man 2 getpid  //查看Linux操作系统提供的系统调用接口、
//由于Linux操作系统是使用C语言写的,故Linux操作系统所提供的系统调用接口在本质上就是C语言函数
//调用接口,这属于Linux操作系统的系统调用接口,在Windows系统下使用该Linux系统下的该系统调用
//接口,应该是不可以的、 
GETPID(2)                     Linux Programmer's Manual                       GETPID(2)                                              
  
NAME
       getpid, getppid - get process identification

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       pid_t getpid(void);   // pid_t 等价于 size_t 、
       pid_t getppid(void);

DESCRIPTION
       getpid() returns the process ID of the calling process.  (This is often used by routines that generate unique temporary filenames.)

       getppid() returns the process ID of the parent of the calling process.

ERRORS
       These functions are always successful.

CONFORMING TO
       POSIX.1-2001, 4.3BSD, SVr4.

NOTES
       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
       getpid() repeatedly.  Normally this caching is invisible, but its correct operation relies on support in the  wrapper  functions  for  fork(2),
       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
       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
       case where getpid() may return the wrong value even when invoking clone(2) via the glibc wrapper function.

SEE ALSO
       clone(2), fork(2), kill(2), exec(3), mkstemp(3), tempnam(3), tmpfile(3), tmpnam(3), credentials(7)

COLOPHON
       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
       found at http://www.kernel.org/doc/man-pages/.
 Manual page getpid(2) line 1 (press h for help or q to quit)q
//新建会话0:
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest.c
[HJM@hjmlcc ~]$ vim mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
  while(1)
  {
    printf("I am a process!,pid:%d\n",getpid());
    sleep(1);
  }
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
code  Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
I am a process!,pid:9457
I am a process!,pid:9457
I am a process!,pid:9457
I am a process!,pid:9457
I am a process!,pid:9457
I am a process!,pid:9457
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 5899  9457  9457  5899 pts/0     9457 S+    1002   0:00 ./mytest         //9457、
[HJM@hjmlcc ~]$ 

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

方法一:

[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
I am a process!,pid:10001
I am a process!,pid:10001
I am a process!,pid:10001
I am a process!,pid:10001
I am a process!,pid:10001
I am a process!,pid:10001
I am a process!,pid:10001
^C
[HJM@hjmlcc ~]$ 
//使用热键 ctrl+c ,即可结束掉正在运行(时实启动)的进程、

方法二:

//新建会话0:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
I am a process!,pid:10470
I am a process!,pid:10470
I am a process!,pid:10470
I am a process!,pid:10470
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ kill -9 10470
//向正在运行(时实启动)的进程发送9号信号,在后期信号中会进行具体的阐述,10470就是我们要结束掉的
//正在运行(时实启动)的进程的PID、
[HJM@hjmlcc ~]$ 


//新建会话0:
...
...
I am a process!,pid:10470
I am a process!,pid:10470
I am a process!,pid:10470
I am a process!,pid:10470
Killed
[HJM@hjmlcc ~]$ 
//此时正在运行(时实启动)的有关可执行程序mytest所形成的进程就被结束掉了、
[HJM@hjmlcc ~]$ man 2 getppid
GETPID(2)               Linux Programmer's Manual               GETPID(2)

NAME
       getpid, getppid - get process identification

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       pid_t getpid(void);
       pid_t getppid(void);

DESCRIPTION
       getpid()  returns the process ID of the calling process.  (This is
       often used by routines that generate unique temporary filenames.)

       getppid() returns the process ID of  the  parent  of  the  calling
       process.

ERRORS
       These functions are always successful.

CONFORMING TO
       POSIX.1-2001, 4.3BSD, SVr4.

NOTES
       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  getpid()  repeatedly.   Normally this caching is invisible,
       but its correct operation relies on support in the  wrapper  func‐
       tions  for  fork(2),  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 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 case where get‐
       pid() may return the wrong value even when invoking  clone(2)  via
 Manual page getppid(2) line 1 (press h for help or q to quit)q
//新建会话0:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
  while(1)
  {
    printf("I am a process!,pid:%d,ppid:%d\n",getpid(),getppid());
    sleep(1);
  }
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
//有关可执行程序mytest所形成的进程的进程ID(PID)为12260,而该进程的父进程ID(PPID)为5899、
I am a process!,pid:12260,ppid:5899
I am a process!,pid:12260,ppid:5899
I am a process!,pid:12260,ppid:5899
I am a process!,pid:12260,ppid:5899
I am a process!,pid:12260,ppid:5899
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 5899 12260 12260  5899 pts/0    12260 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ 


//先把本次有关可执行程序mytest所形成的进程结束掉,然后再重新启动有关可执行程序mytest所形成的
//进程:
//新建会话0:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
//有关可执行程序mytest所形成的进程的进程ID(PID)为13359,而该进程的父进程ID(PPID)为5899、
I am a process!,pid:13359,ppid:5899
I am a process!,pid:13359,ppid:5899
I am a process!,pid:13359,ppid:5899
I am a process!,pid:13359,ppid:5899
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 5899 13359 13359  5899 pts/0    13359 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ 


//由上可知,当我们每一次结束掉上一次有关可执行程序mytest所形成的进程,然后再重新启动有关可执行
//程序mytest所形成的进程时,会发现,这多个由有关可执行程序mytest所形成的进程中的进程ID(PID)都
//不相同,但是这多个由有关可执行程序mytest所形成的进程中的父进程ID(PPID)则都相同、


//不管有关可执行程序mytest所形成的进程是否正在运行(时实启动),而该进程的父进程则都是一直正在
//运行(时实启动)的、


//新建会话0:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
I am a process!,pid:15708,ppid:5899
I am a process!,pid:15708,ppid:5899
I am a process!,pid:15708,ppid:5899
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 5899
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 5898  5899  5899  5899 pts/0    15708 Ss    1002   0:00 -bash       
//上述进程的进程ID(PID)为5899,这也就是有关可执行程序mytest所形成的进程的父进程、
//几乎我们在命令行上所执行的所有的指令,包括运行我们自己编写的程序代码所形成的可执行程序,所形
//成的进程都是bash进程的子进程、
 5899 15708 15708  5899 pts/0    15708 S+    1002   0:00 ./mytest
 8631 16126 16125  8631 pts/1    16125 S+    1002   0:00 grep --color=auto5899
[HJM@hjmlcc ~]$ 

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

        在 Centos7.6 及以上版本中,1号进程换了名字、


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

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

[HJM@hjmlcc ~]$ man 2 fork

//如果成功创建(启动)了当前进程的子进程,则会把当前进程的子进程的PID的值返回给当前进程(父进程)
//的id变量中,把0返回给当前进程的子进程的id变量中,因此,此时的Linux操作系统所提供的系统调用接
//口fork有两个返回值、

//这里是查询Linux操作系统提供的系统调用接口,在本质上,fork也是一个函数,如上,他有两个返回值,在
//之前我们都没有遇到过、

FORK(2)                 Linux Programmer's Manual                 FORK(2)

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 process, referred to as the parent, except for the
       following points:

       *  The child has its own unique process ID, and this PID does  not
          match the ID of any existing process group (setpgid(2)).

       *  The  child's  parent  process  ID  is  the same as the parent's
          process ID.

       *  The child does not inherit its parent's memory locks (mlock(2),
          mlockall(2)).

       *  Process resource utilizations (getrusage(2)) and CPU time coun‐
          ters (times(2)) are reset to zero in the child.

       *  The child's set of pending signals is initially empty (sigpend‐
          ing(2)).

       *  The  child does not inherit semaphore adjustments from its par‐
          ent (semop(2)).

       *  The child  does  not  inherit  record  locks  from  its  parent
          (fcntl(2)).
 Manual page fork(2) line 1 (press h for help or q to quit)/return val
RETURN VALUE
       On success, the PID of the child process is returned in  the  par‐
       ent,  and  0 is returned in the child.  On failure, -1 is returned
       in the parent, no child process  is  created,  and  errno  is  set
       appropriately.

//如果成功创建(启动)了当前进程的子进程,则会把当前进程的子进程的PID的值返回给当前进程(父进程)
//的id变量中,把0返回给当前进程的子进程的id变量中,如果没有成功,则会把-1返回给当前进程(父进程)
//的id变量中,此时并没有成功创建(启动)当前进程的子进程、

ERRORS
       EAGAIN fork()  cannot  allocate sufficient memory to copy the par‐
              ent's page tables and allocate a  task  structure  for  the
              child.

       EAGAIN It  was  not  possible  to create a new process because the
              caller's RLIMIT_NPROC resource limit was  encountered.   To
              exceed  this  limit,  the  process  must  have  either  the
              CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.

       ENOMEM fork() failed to allocate the necessary  kernel  structures
              because memory is tight.

       ENOSYS fork()  is  not  supported  on  this platform (for example,
              hardware without a Memory-Management Unit).

CONFORMING TO
       SVr4, 4.3BSD, POSIX.1-2001.

NOTES
       Under Linux, fork() is implemented using copy-on-write  pages,  so
       the only penalty that it incurs is the time and memory required to
       duplicate the parent's page tables, and to create  a  unique  task
       structure for the child.

       Since version 2.3.3, rather than invoking the kernel's fork() sys‐
       tem call, the glibc fork() wrapper that is provided as part of the
       NPTL  threading  implementation  invokes  clone(2) with flags that
       provide the same effect as the traditional system call.   (A  call
       to  fork() is equivalent to a call to clone(2) specifying flags as
 Manual page fork(2) line 101/154 89% (press h for help or q to quit)q
[HJM@hjmlcc ~]$ ls
Makefile  mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  pid_t id = fork();
  printf("hello,lcc\n");
  sleep(1);
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
hello,lcc
hello,lcc
[HJM@hjmlcc ~]$   //打印了两次、
//这是因为:父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口fork调用处之前和之后
//的所有代码以及该系统调用接口 fork 函数体内部的所有的代码、


//例子:
[HJM@hjmlcc ~]$ ls
lcc.c  Makefile  mytest.c
[HJM@hjmlcc ~]$ cat lcc.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  printf("321\n");
  pid_t id = fork();
  printf("123\n");
  return 0;
}
[HJM@hjmlcc ~]$ gcc lcc.c
[HJM@hjmlcc ~]$ ls
a.out  lcc.c  Makefile  mytest.c
[HJM@hjmlcc ~]$ ./a.out
321
123
123
[HJM@hjmlcc ~]$ 
[HJM@hjmlcc ~]$ ls
Makefile  mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  pid_t id = fork();
  printf("hello,lcc!id:%d\n",id);
  sleep(1);
  return 0;
}
[HJM@hjmlcc ~]$ ls
Makefile  mytest.c
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
hello,lcc!id:23465
hello,lcc!id:0
[HJM@hjmlcc ~]$ ./mytest
hello,lcc!id:23812
hello,lcc!id:0
[HJM@hjmlcc ~]$ ./mytest
hello,lcc!id:23832
hello,lcc!id:0
[HJM@hjmlcc ~]$ 

//上述现象在讲解进程地址空间时再进行阐述、



//新建会话0:
[HJM@hjmlcc ~]$ ls
Makefile  mytest.c
[HJM@hjmlcc ~]$ cat mytest.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  pid_t id = fork();
  if(id == 0)
  {
    //当前进程(父进程)的子进程、
    while(1)
    {
      printf("我是子进程!,我的进程ID(PID)是:%d,我的父进程ID(PPID)是:%d\n",getpi
      sleep(1);
    }
  }
  else{
    //当前进程(父进程)、
    while(1)
    {
      printf("我是父进程!,我的进程ID(PID)是:%d,我的父进程ID(PPID)是:%d\n",getpi
      sleep(1);
    }
  }
  return 0;
}
//在C语言中,if和else不可以同时执行,且在C语言中没有可能同时存在两个或两个以上的死循环、
[HJM@hjmlcc ~]$ make
gcc mytest.c -o mytest
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ./mytest
我是父进程!,我的进程ID(PID)是:19571,我的父进程ID(PPID)是:5899
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
我是父进程!,我的进程ID(PID)是:19571,我的父进程ID(PPID)是:5899
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
我是父进程!,我的进程ID(PID)是:19571,我的父进程ID(PPID)是:5899
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
我是父进程!,我的进程ID(PID)是:19571,我的父进程ID(PPID)是:5899
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
我是父进程!,我的进程ID(PID)是:19571,我的父进程ID(PPID)是:5899
我是子进程!,我的进程ID(PID)是:19572,我的父进程ID(PPID)是:19571
...
...


//新建会话1:
[HJM@hjmlcc ~]$ ls
Makefile  mytest  mytest.c
[HJM@hjmlcc ~]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 5899 19571 19571  5899 pts/0    19571 S+    1002   0:00 ./mytest
19571 19572 19571  5899 pts/0    19571 S+    1002   0:00 ./mytest
[HJM@hjmlcc ~]$ 

//1、
//这是因为:父进程和子进程共享且都会执行Linux操作系统所提供的系统调用接口fork调用处之前和之后
//的所有代码以及该系统调用接口 fork 函数体内部的所有的代码、

//2、
//父进程和子进程各自的id变量中的值不同,在调用Linux操作系统所提供的系统调用接口fork之后,可以
//通过父进程和子进程中各自不同的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 代码时所使用的变量,有可能并不是存在于内存中,实际上,这一个变量名最后会对应到不同的存储空间中,在讲解进程地址空间时再进行具体的阐述、

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脱缰的野驴、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值