(004)linux系统编程


fork 函数

fork 函数用于创建一个进程(创建当前调用此函数的子进程)

  • 父进程的fork返回 子进程ID ;而子进程的fork返回 0,表示进程创建成功
  • getpid函数返回调用此函数的进程ID;getppid函数返回调用此函数的父进程ID
  • getuid函数返回当前进程的实际用户ID;geteuid函数返回当前进程的有效用户ID
  • 在fork之后,父子进程有相同的权利去抢占CPU,并不意味着父进程的优先级一定会比子进程的高,取决于内核所使用的调度算法
  • fork函数遵循 “读时共享,写时复制” 的原则:如果fork后的代码只有读操作,那么共享同一块物理地址;否则复制一份

循环创建多个进程示例:

  • for() { fork(); }循环调用fork函数会创建 2n - 1 个子进程。正确的方法应该如下:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main() {
	pid_t pid;
	int i;
	for (i = 0; i < 5; ++i) {
		pid = fork();
		if (pid == -1) {
			perror("fork error");
			exit(1);
		} else if (pid == 0) {
			break;
		}
	}

	if (i < 5) {
		sleep(i);	// 按创建子进程的顺序打印
		printf("I'm %d child, pid = %u, ppid = %u\n", i+1, getpid(), getppid());
	} else {
		sleep(i);
		printf("I'm parent, pid = %u, ppid = %u\n", getpid(), getppid()); // 这里的ppid是bash/shell
	}
	return 0;
}

在fork以后,父子进程有哪些相同,哪些不同呢?各自独立和共享的又有什么呢?

  • 相同:代码段、堆、栈、用户ID、进程工作目录、信号处理方式等
  • 不同:进程ID、父进程ID、定时器、未决信号集等
  • 全局变量位于data段,父子进程是各自独立的(在做写操作的情况下,否则是共享的)
  • 共享的是文件描述符mmap建立的映射区

gdb调试多进程程序

gdb在调试时默认跟踪父进程,在gdb中设置fork之后的跟踪进程的方法(要在fork函数调用前设置)是

  • set follow-fork-mode child
  • set follow-fork-mode parent

子进程状态(孤儿与僵尸)

孤儿进程:父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程(1号)

僵尸进程:进程终止,父进程尚未回收,子进程0-4G进程地址空间都释放了,但唯独PCB残留在内核中,成为僵尸进程。

  • 僵尸进程不能被kill命令清除,因为kill命令是用来终止进程的,而僵尸进程已经终止。除非把其父进程kill掉,让它变成孤儿进程,被init进程回收
  • PCB存在的意义是为了父进程给子进程“收尸”,例如获取子进程的退出状态导致终止的信号信息

子进程回收

对于已经终止的子进程,它的父进程可以调用 wait 或 waitpid 来获取子进程终止时在内核中残留的PCB信息,然后彻底清除掉这个进程。

1、wait 函数

  • 父进程阻塞,等待子进程退出
  • 回收子进程残留资源
  • 获取子进程结束状态或退出原因

1)进程正常结束:WIFEXITED(status)

  • WEXITSTATUS(status),程序正常结束,用该宏函数获取进程的退出状态

2)进程异常终止:WIFSIGNALED(status)

  • WTERMSIG(status),程序异常终止,用该宏函数获取导致终止的信号编号

2、waitpid 函数

  • -1作为参数1可以设置waitpid函数为回收所有子进程
  • 0做为参数1可以设置waitpid函数回收和当前进程一个组的所有子进程
  • <-1作为参数1可以设置waitpid函数回收指定进程组内的子进程
  • WNOHANG 作为参数3可以设置waitpid函数为非阻塞,此时如果子进程还没结束,返回0
  • 0 作为参数3可以设置waitpid函数为阻塞

exec 函数族

作用是在程序中运行一个程序。当一个进程调用其中一个exec函数时,该进程的用户空间代码和数据完全被新程序替换(.text,.data),从新程序的启动例程(.text第一条指令)开始执行。

  • 调用exec并不创建新进程,所以调用exec前后该进程的ID并没有改变

示例:int execlp(const char* file, const char *arg, ...);,命令行参数以NULL结尾

  • execlp("ls", "ls", "-l", NULL);,第二个参数是argv[0],第二个以后的参数是传递给可执行程序 ls;使用程序名在PATH环境变量中搜索,有环境变量参与。通常用来调用系统可执行程序。
  • execl("/bin/ls", "ls", "-l", NULL);,使用参数1给出的绝对路径搜索,没有环境变量参与。通常用来调用用户自定义可执行程序。

使用实例:利用exec函数,将当前系统中的进程信息打印到文件中

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main () {

    int fd = open("ps.out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
	if (fd < 0) {
		perror("open ps.out error");
		exit(1);
	}
	dup2(fd, STDOUT_FILENO);	// 把参1的文件描述符复制给参2,导致参2指向的文件现在指向参1指向的文件
	execlp("ps", "ps", "ax", NULL);
	perror("exec error");	// exec出错才会执行该语句
	exit(1);
    return 0;
}

管道

管道的实质其实是一个伪文件(套接字、块设备、字符设备和管道四种文件类型都是伪文件,不占用磁盘存储空间)

  • 由一个表示读端和一个表示写端的两个文件描述符所引用,数据从管道的写端流入,从读端流出
  • 内核的实现方式是环形队列,数据先进先出,默认大小是4k
  • 数据不能够重复读取,读走就没了。而且数据的流动具有单向性(半双工)
  • 在有血缘关系的进程用管道做通信时,为了保证数据的单向流动,在定义好读写端之后需要在相应进程中关闭相应的一端

共享内存和mmap

  • mmap创建映射区,返回操作这个映射区的首地址指针。munmap释放映射区
  • 创建映射区(在内核)的权限要小于等于创建的文件(在磁盘)的权限,创建映射区时会对文件进行一次读操作
  • 映射文件的偏移offset一定是4k的整数倍(内核中的MMU来帮助完成映射)
  • MAP_ANONYMOUS这个宏实现匿名映射,就不用多余创建一个文件(然后unlink)了。常用在父子进程通信
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值