Linux0.11内核源码解析-pipe.c

news2024/11/25 10:32:21

目录

什么是PIPE?

PIPE注意事项

有名和匿名管道

内核管道通信

管道读函数

管道写函数

管道创建


什么是PIPE?

进程间通信(IPC,Inter-Process Communication)是指在不同进程间进行数据通信和交换的过程。管道(pipe)是一种进程间通信的机制,它是一种单向、先进先出的通信方式。一个进程将数据写入管道,而另一个进程从管道中读取数据。在Linux或Unix系统中,进程间还可以使用共享内存、信号量、消息队列等不同的IPC机制进行通信。通过IPC,进程可以在互不依赖和独立运行的情况下,共享资源和数据,实现协同完成任务。同时,IPC也需要对进程的安全性和稳定性进行保障,以避免出现数据丢失、资源竞争等问题。

PIPE注意事项

管道是进程间通信的一种方式,使用管道需要注意以下事项:

  1. 管道是单向的:管道只能用于单向数据传输,数据只能由一个进程写入,另一个进程读取。如果两个进程需要进行双向通信,需要创建两个管道。

  2. 管道是有限的:管道具有固定的缓冲区大小,当缓冲区满时,写入进程会被阻塞,直到读取进程读取数据释放缓冲区。同样的,当缓冲区为空时,读取进程会被阻塞,直到写入进程写入数据。

  3. 管道是匿名的:管道是匿名的,没有名称或标识符。管道的创建必须在父进程中完成,子进程通过继承父进程的文件描述符来使用管道。

  4. 管道的传输数据是顺序的:管道中写入的数据按照先后顺序传输,读取进程读取数据的顺序与写入进程写入数据的顺序相同。

  5. 管道的使用需要进程同步:在使用管道时,需要进行进程同步,以确保数据的正确传输和处理。

总之,管道是一个简单而有效的进程间通信方式,但需要注意以上事项,以确保其正确而安全的使用。

有名和匿名管道

在进程间通信中,有名和匿名是用来描述管道的两种不同类型。

匿名管道只存在于内存中,没有文件名和文件系统路径,因此只能用于相关进程之间的通信。匿名管道由父进程创建,通过fork() 创建子进程,子进程继承了管道的读写文件描述符,父子进程就可以通过管道通信。

有名管道(也称为命名管道)则存在于文件系统中,具有文件名和路径,任何进程都可以打开管道进行通信。有名管道需要在文件系统中显示创建,可以使用mkfifo()函数创建一个有名管道。进程可以打开管道文件并向其中写入数据,或者从中读取数据。

总体而言,匿名管道相对简单、高效,但只能用于具有亲缘关系的进程之间通信;而有名管道相对复杂、灵活,任何进程都可以打开它进行通信,但性能相对差一些。

内核管道通信

 

 

管道读函数

这段代码是一个读取管道的函数。它接受一个指向m_inode结构的指针表示管道的i节点、一个缓冲区指针和一个计数值作为参数。

函数使用一个循环,直到读取完所需的字节数为止。在每次循环迭代中,它首先检查管道的大小是否为零。如果是零,则唤醒等待该i节点的进程,并检查是否有写入者。如果没有写入者,函数将返回已读取的字节数。否则,它会将自身进程放入等待队列,并睡眠等待信号。

如果管道的大小非零,函数计算可以从管道中读取的最大字符数chars。它将chars限制为剩余的count和管道大小之间的较小值。然后,它从管道中读取chars个字符,并将其写入缓冲区。读取的字符数和总共读取的字节数都会相应增加。

最后,函数唤醒等待该i节点的进程,并返回已读取的字节数。

int read_pipe(struct m_inode * inode, char * buf, int count)
{
	int chars, size, read = 0;

	while (count>0) {
		while (!(size=PIPE_SIZE(*inode))) {
			wake_up(&inode->i_wait);
			if (inode->i_count != 2) /* are there any writers? */
				return read;
			sleep_on(&inode->i_wait);
		}
		chars = PAGE_SIZE-PIPE_TAIL(*inode);
		if (chars > count)
			chars = count;
		if (chars > size)
			chars = size;
		count -= chars;
		read += chars;
		size = PIPE_TAIL(*inode);
		PIPE_TAIL(*inode) += chars;
		PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
		while (chars-->0)
			put_fs_byte(((char *)inode->i_size)[size++],buf++);
	}
	wake_up(&inode->i_wait);
	return read;
}

管道写函数

这段代码是一个写入管道的函数。它接受一个指向m_inode结构的指针表示管道的i节点、一个缓冲区指针和一个计数值作为参数。

函数使用一个循环,直到写入完所有的字节数为止。在每次循环迭代中,它首先检查管道的可用空间大小是否为零。如果是零,则唤醒等待该i节点的进程,并检查是否有读取者。如果没有读取者,函数将设置当前进程的信号位,表示管道已满,然后返回已写入的字节数如果有写入的话,否则返回-1。然后,它会将自身进程放入等待队列,并睡眠等待信号。

如果管道的可用空间非零,函数计算可以写入管道的最大字符数chars。它将chars限制为剩余的count和可用空间大小之间的较小值。然后,它从缓冲区中读取chars个字符,并将其写入管道。写入的字符数和总共写入的字节数都会相应增加。

最后,函数唤醒等待该i节点的进程,并返回已写入的字节数。

int write_pipe(struct m_inode * inode, char * buf, int count)
{
	int chars, size, written = 0;

	while (count>0) {
		while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
			wake_up(&inode->i_wait);
			if (inode->i_count != 2) { /* no readers */
				current->signal |= (1<<(SIGPIPE-1));
				return written?written:-1;
			}
			sleep_on(&inode->i_wait);
		}
		chars = PAGE_SIZE-PIPE_HEAD(*inode);
		if (chars > count)
			chars = count;
		if (chars > size)
			chars = size;
		count -= chars;
		written += chars;
		size = PIPE_HEAD(*inode);
		PIPE_HEAD(*inode) += chars;
		PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
		while (chars-->0)
			((char *)inode->i_size)[size++]=get_fs_byte(buf++);
	}
	wake_up(&inode->i_wait);
	return written;
}

管道创建

这段代码是用于创建管道的系统调用函数。它接受一个指向文件描述符数组的指针作为参数。

函数首先尝试在文件表中找到两个未使用的文件结构体file。它会逐个检查文件表的条目,如果找到未使用的文件结构体,则将其计数加1,并将其索引加上文件表的基地址,保存到文件结构体数组f[]中。通过这个过程,函数获取了两个可用的文件结构体。

如果只找到一个可用的文件结构体,那么将第一个文件结构体的计数重置为0。

然后,函数在当前进程的文件指针数组中找到两个未使用的槽位,并将之前获得的文件结构体分别存储到这两个槽位中,并将对应的文件描述符保存到fd[]数组中。

如果只找到一个可用的槽位,那么将该槽位设置为NULL。

如果找不到两个可用的槽位,函数返回-1表示创建管道失败。在这种情况下,需要恢复之前增加的文件结构体的计数,并将其重新设置为未使用状态。

如果成功找到两个可用的槽位,函数调用get_pipe_inode()函数获取一个新的管道i节点。如果获取失败,函数将之前分配的文件结构体和槽位进行清理,并返回-1表示创建管道失败。

如果成功获取管道i节点,函数将管道i节点分别赋值给两个文件结构体的f_inode字段。然后,将两个文件结构体的f_pos字段设置为0,并将第一个文件结构体的f_mode字段设置为1表示读取模式,第二个文件结构体的f_mode字段设置为2(表示写入模式)。

最后,函数使用put_fs_long()函数将两个文件描述符保存到用户空间的fildes数组中,并返回0表示成功创建管道。

int sys_pipe(unsigned long * fildes)
{
	struct m_inode * inode;
	struct file * f[2];
	int fd[2];
	int i,j;

	j=0;
	for(i=0;j<2 && i<NR_FILE;i++)
		if (!file_table[i].f_count)
			(f[j++]=i+file_table)->f_count++;
	if (j==1)
		f[0]->f_count=0;
	if (j<2)
		return -1;
	j=0;
	for(i=0;j<2 && i<NR_OPEN;i++)
		if (!current->filp[i]) {
			current->filp[ fd[j]=i ] = f[j];
			j++;
		}
	if (j==1)
		current->filp[fd[0]]=NULL;
	if (j<2) {
		f[0]->f_count=f[1]->f_count=0;
		return -1;
	}
	if (!(inode=get_pipe_inode())) {
		current->filp[fd[0]] =
			current->filp[fd[1]] = NULL;
		f[0]->f_count = f[1]->f_count = 0;
		return -1;
	}
	f[0]->f_inode = f[1]->f_inode = inode;
	f[0]->f_pos = f[1]->f_pos = 0;
	f[0]->f_mode = 1;		/* read */
	f[1]->f_mode = 2;		/* write */
	put_fs_long(fd[0],0+fildes);
	put_fs_long(fd[1],1+fildes);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/666969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生成式AI数据中心网络来了,NVIDIA抢占加速计算高端市场

在大模型和生成式AI的大风口下&#xff0c;NVIDIA大力倡导并率先进军传统数据中心的高端市场——加速计算数据中心。自进入AI和大数据时代&#xff0c;业界就开始出现“加速计算”的概念。简单理解&#xff0c;加速计算即使用GPU、FPGA以及各种DPU等加速芯片以及相关的软件技术…

【Java】POJO类的属性不要命名为isXXX的问题描述,复现,解决方法

问题描述 POJO的属性是布尔类型的时候&#xff0c;采用is_xxx的命名方式&#xff0c;出现参数无法找到的情况 问题复现 Boolean 的属性命名为isA&#xff0c;但是它的getter和setter自动取消了is public class Person { Boolean isA; public Boolean getA() { return is…

locust学习教程(4) - 命令行参数

前言 一句话总结&#xff1a;命令行参数、环境变量、配置文件 1、所有命令行参数 1.1、常用场景参数解读 1.1.1、无web界面&#xff0c;定时运行&#xff0c;数据存储在csv中&#xff1a; locust -f per_01_test.py --headless -u 10 -r 1 -t 1m -s 120 --csvexample --head…

locust学习教程(1)- 概念相关

前言 一句话总结&#xff1a;本文是基于2.4.1的版本去学习locust&#xff0c;如果你想完全搞懂它&#xff0c;那么就从最新的产品文档从头到尾去研读一遍吧。 1、locust是什么&#xff1f; 1.1、相关资料 官网&#xff1a;www.locust.io/产品文档&#xff1a;docs.locust.io…

光伏电站并网雷电防护措施探讨 安科瑞 许敏

摘要: 本文指出了雷击对并网系统光伏电站的主要危害形式及所对应的雷电防护措施。依据相关的防雷及电气接地规范&#xff0c;针对并网系统光伏电站提出了防雷设计方案并做了详细的阐述。在光伏电站的防雷设计中&#xff0c;应考虑雷电会通过何种形式对哪些设施造成损害&#xf…

玩转系统|完美替代ChatGPT!Claude注册教程及出现问题解决方案

目录 1、什么是ChatGPT&#xff1f; 2、什么是Claude&#xff1f; 3、为什么推荐Claude? 3.1、Claude特性 4、注册 slack 5、Claude添加到Slack 6、出现APP Unavailable问题 7、如何解决该问题 8、使用感受 8、1代码测试 8、2文学测试 8、3英语测试 1、什么是ChatGPT&a…

防溺水智能预警监控系统解决方案

一、方案背景 随着夏季暑期的到来&#xff0c;孩童、学生溺水的警钟又不断敲响。预防夏季溺水&#xff0c;不仅要求学校方面要加强安全宣传教育&#xff0c;同时相关部门也需要加强对河流、湖泊、水库、池塘等水域的监控和人员靠近预警。 目前水库、河湖、堤坝、河湖岸线、深水…

图观 智慧交通合集 | 9大行业细分应用案例 一次性看个够!

随着城市化进程的加速和交通需求的不断增长&#xff0c;城市交通系统的安全、高效、智能化的要求越来越高&#xff0c;智慧交通正成为现代城市发展的必然趋势。数字孪生技术的出现&#xff0c;为智慧交通领域的应用提供了更为广阔的空间。 数字冰雹深耕数字孪生行业十余载&…

【Java高级语法】(九)IO流:肝了三天三夜,我打赌没有比我这边更细的探索Java I\O流的文章了~

Java高级语法详解之IO流 :one: 概念1.1 输入流和输出流1.2 字节流和字符流 :two: 优势和缺点:three: 使用3.1 File 类3.2 RandomAccessFile 类3.3 字节流3.3.1 文件字节流3.3.2 缓冲字节流3.3.3 基本数据类型字节流3.3.4 打印流3.3.5 对象序列化流3.3.6 字节数组流 3.4 字符流3…

论文笔记 - 对话系统中的 OOD (Out of Domain出域)问题

徐阿衡 人工智能与机器学习工程师 最近看了下 2021年关于 OOD 的几篇 paper&#xff0c;记录一下~ 对话系统中的 domain 都是预先定义好的&#xff0c;而在实际应用场景中&#xff0c;会有很多现有系统回答不了的问题&#xff08;out of the design scope&#xff09;&#…

locust学习教程(3)- 编写locust脚本

前言 一句话总结&#xff1a;并发的用户执行了第一类测试任务、第二类测试任务&#xff0c;设置所有类的测试前置、测试后置&#xff0c;设置每一类测试任务的测试前置&#xff0c;测试后置。 1、概念 1.1、一个完整的脚本示例 from locust import task, HttpUser, constant…

ASEMI代理光宝光耦LTV-50L的工作原理及应用领域

编辑-Z 本文将对光耦LTV-50L进行详细的介绍&#xff0c;包括其工作原理、性能特点、应用领域以及注意事项。通过阅读本文&#xff0c;您将对光耦LTV-50L有更深入的了解&#xff0c;以便在实际应用中更好地发挥其作用。 1、光耦LTV-50L的工作原理 光耦LTV-50L是一种光电器件&a…

uni-table 表格的封装

文章目录 项目场景&#xff1a;实现效果创建表格组件文件页面中使用实现方法 项目场景&#xff1a; 在实际的应用场景中&#xff0c;表格是一个非常常见的需求&#xff0c;如果每一个的表格都自己去手写的话非常的浪费时间&#xff0c;并且当中的代码冗余量非常大&#xff0c;…

Python--元组

Python--元组 <font colorblue>一、创建元组<font colorblue>二、访问元组元素<font colorblue>三、元组的增、删、查、改<font colorblue>1、添加元素<font colorblue>2、删除元素<font colorblue>3、查找元素<font colorblue>4、修…

甄品进化 | 燕小千智能助手,用AIGC撬动企业知识宝藏

背景&#xff1a;2022年AIGC&#xff08;AI-Generated Content,人工智能生成内容&#xff09;这个新概念横空出世&#xff0c;不仅被消费者追捧&#xff0c;而且备受投资界的关注&#xff0c;更是被技术和产业界竞相追逐。2022年12月&#xff0c;OpenAI的大型语言生成模型ChatG…

Android 60问60答 (一篇复习整个Android)

Android 60问60答 &#xff08;一篇复习整个Android&#xff09; 有哪些移动端平台&#xff1f; 厂商开发平台&#xff1a; los 黑莓&#xff08;blackBerry&#xff09; 第三方私有平台&#xff1a;第三方开发供移动设备厂商使用 WindowsMobile 免费开源平台&#xff1…

微信小程序克隆到运行

1.git克隆 2.安装依赖 npm i 如果遇到卡在node lib/install.js 一直不进行 重新运行安装&#xff1a;(https://www.python100.com/html/3716RLP8FZM2.html) npm install --ignore-scripts理解npm install --ignore-scripts 3.安装完运行 npm run serve如果报错&#xff1a; …

基于改进多目标粒子群算法的配电网储能选址定容——附Matlab代码

目录 摘要&#xff1a; 主要内容&#xff1a; 程序思路&#xff1a; 储能选址定容优化模型&#xff1a; &#xff08;1&#xff09;节点电压波动&#xff1a; &#xff08;2&#xff09;负荷波动&#xff1a; &#xff08;3&#xff09;储能系统容量&#xff1a; 改进的…

2023年最好用的办公AI工具,让你工作效率提升10倍!

2023年是AI工具大爆发的一年&#xff0c;在效率办公领域&#xff0c;同样涌现出了很多优秀的AI办公工具&#xff0c;小编亲测了几款&#xff0c;都是宝藏好用的App&#xff0c;以下排名不分先后&#xff0c;一起来看看吧&#xff01; AI办公工具哪个好 GitMindNotion AI酷表C…

智能优化算法之黏菌优化算法(SMA),附matlab代码

黏菌算法是2020年提出的一种智能优化算反&#xff0c;主要模拟的是自然界中多头绒泡菌在不同食物浓度下的觅食行为以及状态变化。黏菌主要分泌酶来消化食物&#xff0c;黏菌的前端延伸成扇形&#xff0c;后端由相互连接的静脉网络包围。环境中不同浓度的食物影响着黏菌静脉网络…