0
点赞
收藏
分享

微信扫一扫

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

就是耍帅 2022-11-15 阅读 121

目录

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:以特定格式进行显示、
//把 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 ~]$ 

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 ~]$ 

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变量中的值进行判断,让父进程和子进程分别执行不同的代码块、
举报

相关推荐

0 条评论