linux——进程


❀保持低旋律节奏->个人主页

专栏链接:《C++学习》《Linux学习》


文章目录

一、什么是进程?

进程得概念

进程=程序本身得代码和数据+操作系统内核对应的数据结构

进程可以是正在被执行的程序、可以是被加载到内存里的程序

但是进程统一特点是运行的程序

1.1进程控制块PCB

所有进程它所对应的 数据结构和结构体 都能在操作系统内核里面找到。

而每一个进程它所对应的结构体叫做 进程控制块------PCB

进程控制块里面 存在程序它所对应的结构 和属性

这些属性包括

PCB(struct_task)属性
标识符:PID
状态
优先级
程序计数器
内存指针:指向实实在在的代码
上下文数据
I/O状态信息
记账信息(功能类似日志)
1.2.进程的管理

每个程序操作系统内核当中都能找到它们所对应的数据结构------PCB,PCB里面包含程序所有属性,以及结构体。而这些所有的PCB默认是以链表的形式链接在一起。

因此操作系统对进程的管理->操作系统对链表的增删查改

二、 为什么要存在进程?

所有的指令执行、工具执行、程序执行 都必须转化为进程

我们再Windows下 所有通过双击打开的东西 都是进程

进程就是用户想要做什么、进程就是用户的意志!

三、如何通过代码管理进程?

PCB存在于操作系统内核部分,而用户没有直接访问操作系统内核的权限。

因此有且仅有唯一的办法访问操作系统内核------系统调用

系统调用函数

3.1第一个系统调用------getpid函数

man getpid

getpid 的使用需要包含头文件

#include <sys/types.h>

#include <unistd.h>

c 复制代码
  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7   while(1)
  8   {
  9     pid_t id = getpid();
 10     printf("pid:%d\n",id);
 11     sleep(1);                                                            
 12   }
 13   return 0;
 14 }

执行结果

3.2查看进程

查看进行有两种形式

  • 第一种是再根目录下访问 proc文件
  • 第二种使用ps命令

第一种访问方法

cd /

less/head/ls proc

bash 复制代码
[ljy@VM-0-12-centos /]$ ls proc
1      15173  24     386   615        execdomains  net
10     1588   25     4     616        fb           pagetypeinfo
1007   16     252    411   617        filesystems  partitions
1072   16081  26     4119  618        fs           sched_debug
1074   1731   262    4126  619        interrupts   schedstat
1077   17617  265    4127  620        iomem        scsi
109    18     266    413   65         ioports      self
11     18583  267    46    7          irq          slabinfo
12     19     26876  48    7031       kallsyms     softirqs
1242   19364  27     49    8          kcore        stat
1246   19377  270    50    9          keys         swaps
1255   199    271    51    acpi       key-users    sys
1256   2      28     522   buddyinfo  kmsg         sysrq-trigger
1286   20     287    5338  bus        kpagecount   sysvipc
1288   20098  29     5353  cgroups    kpageflags   timer_list
1289   20109  291    5423  cmdline    loadavg      timer_stats
1298   2013   292    5424  consoles   locks        tty
13     21     3359   588   cpuinfo    mdstat       uptime
14     22     3479   593   crypto     meminfo      version
14695  23     35     595   devices    misc         vmallocinfo
14714  23304  36     596   diskstats  modules      vmstat
14953  23315  37     6     dma        mounts       xpmem
14993  23856  38     600   driver     mtrr         zoneinfo

第二种访问方法!推荐

ps ajx

bash 复制代码
[ljy@VM-0-12-centos 12-12]$ ps ajx
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0  32:01 /usr/lib/systemd/sys
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     4     0     0 ?           -1 S<       0   0:00 [kworker/0:0H]
    2     6     0     0 ?           -1 S        0   0:34 [ksoftirqd/0]
    2     7     0     0 ?           -1 S        0   0:06 [migration/0]
    2     8     0     0 ?           -1 S        0   0:00 [rcu_bh]
    2     9     0     0 ?           -1 S        0   4:48 [rcu_sched]
    2    10     0     0 ?           -1 S<       0   0:00 [lru-add-drain]
    2    11     0     0 ?           -1 S        0   0:02 [watchdog/0]
    2    12     0     0 ?           -1 S        0   0:02 [watchdog/1]
    2    13     0     0 ?           -1 S        0   0:06 [migration/1]
    2    14     0     0 ?           -1 S        0   0:29 [ksoftirqd/1]
    2    16     0     0 ?           -1 S<       0   0:00 [kworker/1:0H]
    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:00 [khungtaskd]
    2    21     0     0 ?           -1 S<       0   0:00 [writeback]
    2    22     0     0 ?           -1 S<       0   0:00 [kintegrityd]
    2    23     0     0 ?           -1 S<       0   0:00 [bioset]
    2    24     0     0 ?           -1 S<       0   0:00 [bioset]
    2    25     0     0 ?           -1 S<       0   0:00 [bioset]
    2    26     0     0 ?           -1 S<       0   0:00 [kblockd]
    2    27     0     0 ?           -1 S<       0   0:00 [md]
    2    28     0     0 ?           -1 S<       0   0:00 [edac-poller]
    2    29     0     0 ?           -1 S<       0   0:00 [watchdogd]
    2    35     0     0 ?           -1 S        0   0:00 [kswapd0]
    2    36     0     0 ?           -1 SN       0   0:00 [ksmd]
    2    37     0     0 ?           -1 SN       0   0:01 [khugepaged]
    2    38     0     0 ?           -1 S<       0   0:00 [crypto]
    2    46     0     0 ?           -1 S<       0   0:00 [kthrotld]
    2    48     0     0 ?           -1 S<       0   0:00 [kmpath_rdacd]
    2    49     0     0 ?           -1 S<       0   0:00 [kaluad]
    2    50     0     0 ?           -1 S<       0   0:00 [kpsmoused]
    2    51     0     0 ?           -1 S<       0   0:00 [ipv6_addrconf]
    2    65     0     0 ?           -1 S<       0   0:00 [deferwq]
    2   109     0     0 ?           -1 S        0   0:04 [kauditd]
    2   199     0     0 ?           -1 S<       0   0:00 [iscsi_eh]
    2   252     0     0 ?           -1 S<       0   0:00 [ata_sff]
    2   262     0     0 ?           -1 S        0   0:00 [scsi_eh_0]
    2   265     0     0 ?           -1 S<       0   0:00 [scsi_tmf_0]
    2   266     0     0 ?           -1 S        0   0:00 [scsi_eh_1]
    2   267     0     0 ?           -1 S<       0   0:00 [scsi_tmf_1]
    2   270     0     0 ?           -1 S<       0   0:00 [ttm_swap]
    2   271     0     0 ?           -1 S<       0   0:06 [kworker/1:1H]
    2   287     0     0 ?           -1 S<       0   0:38 [kworker/0:1H]
    2   291     0     0 ?           -1 S        0   1:53 [jbd2/vda1-8]
    2   292     0     0 ?           -1 S<       0   0:00 [ext4-rsv-conver]
    1   386   386   386 ?           -1 Ss       0   0:20 /usr/lib/systemd/sys
    1   411   411   411 ?           -1 Ss       0   0:00 /usr/sbin/lvmetad -f
    1   413   413   413 ?           -1 Ss       0   0:00 /usr/lib/systemd/sys
    1   522   522   522 ?           -1 S<sl     0   0:07 /sbin/auditd
    1   588   588   588 ?           -1 Ss       0   0:26 /usr/lib/systemd/sys
    1   593   593   593 ?           -1 Ss     998   0:03 /usr/bin/lsmd -d
    1   595   595   595 ?           -1 Ssl    999   0:22 /usr/lib/polkit-1/po
    1   596   596   596 ?           -1 Ss      81   1:02 /usr/bin/dbus-daemon
    1   600   600   600 ?           -1 Ss       0   0:00 /usr/sbin/acpid
    2   615     0     0 ?           -1 S<       0   0:00 [ib-comp-wq]
    2   616     0     0 ?           -1 S<       0   0:00 [kworker/u5:0]
    2   617     0     0 ?           -1 S<       0   0:00 [ib-comp-unb-wq]
    2   618     0     0 ?           -1 S<       0   0:00 [ib_mcast]
    2   619     0     0 ?           -1 S<       0   0:00 [ib_nl_sa_wq]
    2   620     0     0 ?           -1 S<       0   0:00 [mlx5_ib_sigerr_]
    1  1007  1007  1007 ?           -1 Ss       0   0:00 /sbin/dhclient -q -l
    1  1072  1072  1072 ?           -1 Ssl      0   1:13 /usr/bin/python2 -Es
    1  1074  1074  1074 ?           -1 S<Ls     0   0:00 /sbin/iscsid -f
    1  1077  1077  1077 ?           -1 Ssl      0   0:00 /usr/sbin/rshim
    1  1242  1242  1242 ?           -1 Ssl      0   0:42 /usr/sbin/rsyslogd -
    1  1246  1246  1246 ?           -1 Ss       0   0:00 /usr/sbin/sshd -D
    1  1255  1255  1255 ?           -1 Ss       0   0:05 /usr/sbin/crond -n
    1  1256  1256  1256 ?           -1 Ss       0   0:00 /usr/sbin/atd -f
    1  1286  1286  1286 ?           -1 Ss       0   0:03 /usr/libexec/postfix
    1  1288  1288  1288 tty1      1288 Ss+      0   0:00 /sbin/agetty --nocle
    1  1289  1289  1289 ttyS0     1289 Ss+      0   0:00 /sbin/agetty --keep-
 1286  1298  1286  1286 ?           -1 S       89   0:00 qmgr -l -t unix -u
    1  1588  1586  1586 ?           -1 Sl       0   0:06 /usr/local/qcloud/st
    1  1731  1729  1729 ?           -1 Sl       0   2:11 /usr/local/qcloud/ta
    1  2013  2013  2013 ?           -1 Ss      38   0:01 /usr/sbin/ntpd -u nt
    1  3359  1374  1374 ?           -1 Sl       0 221:27 /usr/local/qcloud/Yu
    1  3479  1374  1374 ?           -1 Sl       0   5:45 /usr/local/qcloud/Yu
    1  4119  4118  4118 ?           -1 S        0   0:05 barad_agent
 4119  4126  4118  4118 ?           -1 S        0   5:51 barad_agent
 4119  4127  4118  4118 ?           -1 Sl       0  64:20 barad_agent
 1246  5338  5338  5338 ?           -1 Ds       0   0:00 sshd: root@pts/0
 5338  5353  5353  5353 pts/0    19231 Ss       0   0:00 -bash
 5353  5423  5423  5353 pts/0    19231 S        0   0:00 su - ljy
 5423  5424  5424  5353 pts/0    19231 S     1001   0:00 -bash
 1286  7031  1286  1286 ?           -1 S       89   0:00 pickup -l -t unix -u
    1 14695 14695 14695 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 14714 14714 14714 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    2 14993     0     0 ?           -1 S        0   0:00 [kworker/u4:1]
    2 15173     0     0 ?           -1 S        0   0:00 [kworker/1:0]
    2 16081     0     0 ?           -1 S        0   0:00 [kworker/0:0]
    2 17617     0     0 ?           -1 S        0   0:00 [kworker/0:2]
    2 18770     0     0 ?           -1 R        0   0:00 [kworker/0:1]
 5424 19231 19231  5353 pts/0    19231 R+    1001   0:00 ps ajx
    1 19364 19364 19364 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 19377 19377 19377 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 20098 20098 20098 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 20109 20109 20109 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 23304 23304 23304 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    1 23315 23315 23315 ?           -1 Ssl   1001   0:00 /home/ljy/.VimForCpp
    2 23856     0     0 ?           -1 S        0   0:01 [kworker/1:1]
    2 26876     0     0 ?           -1 S        0   0:05 [kworker/u4:2]

ps + 管道 +grep

ljy 用户 执行proc.exe 得到进程号 22292

root 用户查看 进程号2292所有程序

bash 复制代码
[root@VM-0-12-centos ~] ps ajx | head -1 && ps ajx | grep 22292
3.2.1TTY 终端

echo "aaa" > /dev/pts/0

发现可以向终端发送数据

3.3cwd获取当前路径
c 复制代码
  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7   char buf[1024];
  8   while(1)
  9   {
 10     pid_t id = getpid();
 11     printf("pid:%d\n",id);
 12     getcwd(buf,sizeof(buf));
 13     printf("getcwdL%s\n",buf);                                           
 14     sleep(1);
 15   }
 16   return 0;
 17 }
3.4bash

每一次登录系统都会自动提供bash来对命令行服务

bash 是命令解释器、本身也是进程 它是一个死循环

四、fork()函数

c 复制代码
  1 #include<stdio.h>                                                                                                                                        
  2 #include<unistd.h> //fork()\getpid()\getppid()头文件
  3 #include<sys/wait.h> //wait头文件
  4 #include<stdlib.h> //exit()头文件
  5 
  6 int main()
  7 {
  8 
  9   //1.打印父进程的初始信息
 10   printf("----父进程的初始信息----\n");
 11   printf("父进程PID:%d,父进程PPID:%d\n",getpid(),getppid());
 12   printf("--------------------\n");
 13 
 14   //2.调用fork()创建子进程
 15   pid_t pid = fork();
 16   //3.处理错误:fork()失败
 17   if(pid ==-1)
 18   {
 19     perror("fork调用失败"); //打印错误原因
 20     exit(EXIT_FAILURE);
 21   }
 22   //4.子进程逻辑 (fork()返回0)
 23   else if (pid == 0)
 24   {
 25     printf("----子进程执行逻辑----\n");
 26     printf("子进程PID:%d\n",getpid());
 27     printf("子进程中fork()返回值:%d\n",pid);
 28     printf("--------------------\n");
 29     printf("所有程序执行完毕\n");
 30   }
 31   //5.父进程的执行逻辑(fork()返回子进程的PID)
 32   else 
 33   {
 34     //等待子进程执行完毕,避免父进程先退出导致子进程编程孤儿进程
 35     wait(NULL);
 36     printf("----父进程后续逻辑----\n");
 37     printf("父进程PID:%d\n",getpid());
 38     printf("父进程中fork()返回值:%d\n",pid);
 39     printf("--------------------\n");
 40     printf("所有程序执行完毕\n");
 41     
 42   }
 43   return 0;
 44 }

执行结果

c 复制代码
----父进程的初始信息----
父进程PID:16422,父进程PPID:25886
--------------------
----子进程执行逻辑----
子进程PID:16423
子进程中fork()返回值:0
--------------------
所有程序执行完毕
----父进程后续逻辑----
父进程PID:16422
父进程中fork()返回值:16423
--------------------
所有程序执行完毕

👍fork三个问题

那么我们通过代码头次接触fork会存在诸多问题。下面就挑选几个核心问题然后进行解答

  • 1.fork之后为什么给子进程返回0,给父进程返回子进程的pid?

父进程需要子进程 PID:便于管理多个子进程(如waitpid等待指定子进程、kill给指定子进程发信号);

子进程返回 0:0 是永远不会被分配给真实进程的特殊值,用于快速标识 "当前进程是子进程"(子进程可通过getppid()获取父进程 PID);

失败时统一返回 - 1,作为创建失败的唯一标识。

  • 2.同一函数为什么能被返回2次?
    pid_t id = fork()是系统调用函数,那么它在if else if else分支中理应只能执行其中一个分支。那么为什么id技能==0又能>0呢?

fork 调用触发内核复制出子进程,父子进程成为两个独立的执行流;内核给两个执行流的id分别赋值(子进程 id=0、父进程 id = 子进程 PID);最终两个进程各自执行 if/else 分支,仅走其中一个分支 ------ 从程序员视角看,表现为 "一次调用,两次返回"。

本质是因为它们是两个独立的执行流

  • 3.同一变量id为什么即==0又>0?

因为id是两个独立进程中拥有相同虚拟地址的不同物理变量

本质是两个id不是同一个变量(实现方法 虚拟内存+写实拷贝

最终精简版(可直接用)

对的!本质是两个 id 不是同一个变量;其中「虚拟内存的地址映射」是实现 "同虚拟地址、不同物理变量" 的核心机制,而写时拷贝(COW)是 fork 过程中减少内存拷贝的高效优化手段,二者共同保障了这个逻辑的实现。

相关推荐
YFLICKERH2 小时前
【Linux系统】ubuntu - python 虚拟环境搭建|使用|与系统环境的区别
linux·python·ubuntu·虚拟环境
Ha_To2 小时前
2025.12.19 OSPF
运维·服务器·网络
proware2 小时前
3588 cma heap应用示例之图像采集
linux·cma·dma buf
羊村懒哥2 小时前
告别命令行查日志!CentOS 安装 ELK 实现可视化监控
linux·elk·centos
txzz88882 小时前
CentOS-Stream-10 YUM本地仓配置
linux·运维·centos·yum·yum本地仓配置
HalvmånEver2 小时前
Linux:Ext系列⽂件系统(三)
linux·运维·服务器
伍叁_2 小时前
shell脚本案例
linux·运维·服务器
qq_5470261792 小时前
Linux 文件与目录管理
linux·运维·服务器
宸津-代码粉碎机2 小时前
告别繁琐SQL!MyBatis - Flex让数据库操作“飞”起来
java·服务器·tomcat