Linux系统应用编程 --- 进程原语(一)

简介: Linux系统应用编程 --- 进程原语(一)

进程原语一. fork函数

1. 函数原型

pid_t fork(void);

子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。

2. 以具体的程序讲解fork函数特点

第一段代码

1. #include <stdio.h>
2. #include <sys/types.h>
3. #include <unistd.h>
4. 
5. int main(void)
6. {     
7. //fork创建一个新进程
8.        pid_t p1 = -1;
9. 
10. //fork之前的操作只有父父进程才有
11.        p1 = fork();    //调用一次fork函数会返回两次
12. 
13. if(p1 == 0)
14.        {
15. //这里一定是子进程
16. //先sleep一下,让父进程先死
17.               sleep(1);
18. 
19.               printf("子进程, pid = %d.\n", getpid());
20.               printf("子进程, p1 = %d.\n", p1);
21.               printf("子进程中父进程的ID = %d.\n", getppid());
22.        }
23. if(p1 > 0)
24.        {
25. //这里一定是父进程
26.               printf("父进程, pid = %d.\n", getpid());
27.               printf("父进程, p1 = %d.\n", p1);
28.        }
29. 
30. if(p1 < 0)
31.        {
32. 
33. //这里一定是出错了
34.        }
35. 
36. //在这里的操作,父子进程都有
37. //printf("hello world, pid = %d.\n", getpid());
38. 
39. return 0;
40. }

输出结果如下:

结论:

1. 结论:
2. 
3. (1)fork函数调用一次会返回两次,返回值等于0的就是子进程,返回值大于0的就是父进程
4. 
5. (2)fork的返回值在子进程中等于0, 在父进程中返回值等于本次fork创建的子进程的PID
6. 
7. (3)这里在子进程中打印父进程PID,为什么跟在父进程中打印父进程的PID结果不一样?
8. 
9. 是因为在执行的时候,父进程先执行完,然后子进程就没有父进程了;这是在子进程中打印的父进程PID就是init进程

 

第二段代码

1. #include <stdio.h>
2. #include <unistd.h>
3. #include <stdlib.h>
4. #include <sys/types.h>
5. 
6. int main(void)
7. {
8.        pid_t pid ;
9. //调用一次返回2次,在父进程返回子进程的PID,在子进程中返回0
10. 
11.        int n = 10;
12.        pid = fork();
13. 
14. if(pid > 0)
15.        {/*in parent*/
16.               while(1)
17.               {
18.                      printf("I am parent %d\n", n++);
19.                      printf("my pid = %d.\n", getpid());
20.                      printf("my parent pid = %d.\n", getppid());
21.                      sleep(1);
22.               }
23.        }
24. 
25. else if(pid == 0)
26.        {/*in child*/
27.               while(1)
28.               {
29.                      printf("I am child %d\n", n++);
30.                      printf("my pid = %d.\n", getpid());
31.                      printf("my parent pid = %d.\n", getppid());
32.                      sleep(3);
33. 
34.               }
35.        }
36. 
37. else
38.        {
39.               perror("fork");
40. exit(0);
41.        }
42. 
43. return 0;
44. }

结论:

1. (1)父子进程中n值分别独立加,说明子进程从父进程中克隆过来的数据,已经不是共享的了。两者有自己独立的空间。
2. 
3. (2)0-3G放应用层代码,子进程直接从父进程中拷贝,3-4G是内核空间
4. 
5. (3)读时共享,写时复制(copy on write)(好处:节省物理内存开销,省去直接复制的时间)

fork函数创建子进程之后,如果只是用返回值去区分父子进程,这样的方式效率太低,下面会介绍更好的方法!!!

 

相关文章
|
2月前
|
Ubuntu Linux Anolis
Linux系统禁用swap
本文介绍了在新版本Linux系统(如Ubuntu 20.04+、CentOS Stream、openEuler等)中禁用swap的两种方法。传统通过注释/etc/fstab中swap行的方式已失效,现需使用systemd管理swap.target服务或在/etc/fstab中添加noauto参数实现禁用。方法1通过屏蔽swap.target适用于新版系统,方法2通过修改fstab挂载选项更通用,兼容所有系统。
202 3
Linux系统禁用swap
|
2月前
|
Linux
Linux系统修改网卡名为eth0、eth1
在Linux系统中,可通过修改GRUB配置和创建Udev规则或使用systemd链接文件,将网卡名改为`eth0`、`eth1`等传统命名方式,适用于多种发行版并支持多网卡配置。
270 3
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
260 0
Linux系统初始化脚本
|
2月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
244 1
|
缓存 Linux 测试技术
安装【银河麒麟V10】linux系统--并挂载镜像
安装【银河麒麟V10】linux系统--并挂载镜像
5725 0
|
关系型数据库 MySQL Linux
卸载、下载、安装mysql(Linux系统centos7)
卸载、下载、安装mysql(Linux系统centos7)
441 0
|
Linux
手把手教会你安装Linux系统
手把手教会你安装Linux系统
228 0
|
Linux 虚拟化 数据安全/隐私保护
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
|
Ubuntu Linux 网络安全
从头安装Arch Linux系统
本文记录了作者安装Arch Linux系统的过程,包括安装成果展示和遇到的疑难点及其解决方法,如硬盘不足、下载失败、设置时区、安装微码和配置无密码登录等。
425 1
从头安装Arch Linux系统
|
存储 NoSQL Java
使用redis进行手机验证码的验证、每天只能发送三次验证码 (redis安装在虚拟机linux系统中)
该博客文章展示了如何在Linux虚拟机上使用Redis和Jedis客户端实现手机验证码的验证功能,包括验证码的生成、存储、验证以及限制每天发送次数的逻辑,并提供了测试结果截图。
使用redis进行手机验证码的验证、每天只能发送三次验证码 (redis安装在虚拟机linux系统中)