Linux-0.11 文件系统pipe.c详解

news2024/11/27 12:39:36

Linux-0.11 文件系统pipe.c详解

模块简介

在Linux-0.11中提供了管道这种进程间通讯的方式。本程序包含了管道文件读写操作函数read_pipe()和write_pipe()。

函数详解

read_pipe

int read_pipe(struct m_inode * inode, char * buf, int count)

该函数是读管道的方法。

pipe

函数的最初定义了一些参数,其中chars为需要复制的字符数,size的作用有两个,在下面的代码中会根据代码介绍,read参数代表已经读取的字符数。

int chars, size, read = 0;

因为管道的大小最大只有4k,因此当count的值大于4K时,就涉及到多次读,因此通过一个大的循环,当count值大于0,便循环执行下面的操作。如果管道中的数据长度为0,那么就唤醒等待该管道inode的进程(通常是写pipe的进程)。如果目前没有写管道的进程,意味着当前pipe不可能读到数据,则将当前进程加入到等待该inode的队列中。

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的值等于管道尾指针到缓冲区末端的字节数。 如果其大于count值,那么令其等于count。如果chars大于管道中含有数据的长度size, 则令chars等于size。接下来令剩下待读的字符数减去chars,令已经读取的字符数read加上chars。

chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count)
    chars = count;
if (chars > size)
    chars = size;
count -= chars;
read += chars;

接下来将size指向原来尾指针的位置,将尾指针向前移动chars,如果超过4k,则返回头重新开始。最后调用put_fs_byte将管道中的数据复制到用户缓冲区中。

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;

write_pipe

int write_pipe(struct m_inode * inode, char * buf, int count)

该函数是管道的写操作函数。

函数的开始定义了一些参数,其中chars是要写入管道的数量,size有多个作用,written是已经写入的字符数量。

int chars, size, written = 0;

因为管道的大小最大只有4k,因此当count的值大于4K时,就涉及到多次写,因此通过一个大的循环,当count值大于0,便循环执行下面的操作。如果当前管道已经满,那么便唤醒等待该pipe inode的进程(读进程)。如果当前的inode节点没有其他的读进程,则发送SIGPIPE信号到进程。否则的话,则将当前进程加入sleep队列,直到pipe inode可写。

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。如果chars大小大于count,则令chars等于count。接下来如果chars大于size值,则令chars等于size。接下来令count值减去chars值,令已写数据written加上chars值。

chars = PAGE_SIZE-PIPE_HEAD(*inode);
if (chars > count)
    chars = count;
if (chars > size)
    chars = size;
count -= chars;
written += chars;

最后将size指向头节点,将PIPE_HEAD向前推进chars个字符。最后调用get_fs_byte,从buf拷贝数据到pipe缓冲区中。

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++);

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

    wake_up(&inode->i_wait);
    return written;

sys_pipe

int sys_pipe(unsigned long * fildes)

该函数是创建管道pipe函数的系统调用。

入参fildes是管道的文件描述符,(fildes+0)是读端,(fildes+1)是写端。

程序的开始,定义了一系列变量。其中,inode用于获取管道类型的inode。f数组用于从文件表中找到两个空位。fd数组是管道的读端和写端。 i和j用于遍历。

    struct m_inode * inode;
    struct file * f[2];
    int fd[2];
    int i,j;

接下来要做的就是从全局文件表file_table中找到两个空位。如果找不到两个空位,就返回-1。

    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;

接下来从进程的文件表中获取两个空位,用于填充文件描述符数组fd[2]。同样,如果没有两个空位,则返回-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;
    }

接下来便是获取一个空的inode节点用作管道读写的inode。如果没有空的inode节点,则返回-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;
    }

如果管道inode节点申请成功,则对两个文件结构进行初始化。并通过put_fs_long将文件描述符拷贝到入参fildes中。

    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);

Q & A

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

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

相关文章

python绘图工具matpoltlib的常用操作

目录 1.matplotlib概述2.风格设置3.条形图4.盒图5.直方图和散点图6.3D图7.pie图和布局8.Pandas与sklearn结合实例 1.matplotlib概述 Matplotlib 是一个用 Python 编程语言编写的、基于 NumPy 的开源数据可视化库。它提供了一套完整的兼容 MATLAB 的 API&#xff0c;支持各种常…

如何在华为OD机试中获得满分?Java实现【贪心的商人】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

Unity之2D碰撞器

1、什么是碰撞器 碰撞器是用于在物理系统中 表示物体体积的的&#xff08;形状或范围&#xff09; 刚体通过得到碰撞器的范围信息进行计算 判断两个物体的范围是否接触 如果接触 刚体就会模拟力的效果产生速度和旋转 2、参数 Edit Collider&#xff1a;编辑碰撞器 Material…

chatgpt赋能python:Python校验和的介绍

Python 校验和的介绍 在计算机科学中&#xff0c;校验和是一种用于检测数据传输中错误的简单方法。它可以用来确保数据在传输过程中没有发生丢失、损坏或篡改。Python语言中&#xff0c;我们可以通过各种方法来计算校验和。 常用的校验和算法 Python中常见的校验和算法包括&…

chatgpt赋能python:Python绘图颜色

Python绘图颜色 Python是一种通用编程语言&#xff0c;也是数据科学和机器学习领域中最受欢迎的语言之一。Python的一个强大的功能是绘图&#xff0c;它可以用来呈现数据和信息的可视化。 在Python绘图中&#xff0c;颜色是一个非常重要的元素。颜色可以帮助我们更好地理解数…

英睿达内存条正品鉴别教程(镁光颗粒)

我们打算买一款二手镁光颗粒的英睿达内存条,需要从正面内存标签上的条形码、字串,从背面颗粒上的两行字符一一分析、检查、鉴别,最终确认是否正品,以及内存条等级如何。通过本片文章,您能学会如何进行镁光颗粒的英睿达内存条正品鉴别。 一、标签检查 首先,用百度条形码…

win11还原win10磁贴方法ExplorerPatcher,替代Start 11、StartALLBack(开源免费~)

文章目录 1.简介2.解决方案3.ExplorerPatcher3.1功能概要3.2软件安装3.3软件卸载 4.操作使用&#xff08;部分&#xff09;4.1磁贴开启4.2磁贴使用小技巧4.3优化建议4.4注意事项 5.下载地址 1.简介 微软&#xff1a;我不向前兼容&#xff0c;用户喷我兼容性差。我向前兼容&…

搭建自己的pts性能测试平台--jmeter+influxdb+chronograf+grafana

不知道大家有没有使用过阿里的性能工具pts&#xff0c;详细的数据视图不要太香&#xff0c;唯一的缺点就是收费。那有没有类似的这种平台&#xff0c;让我们可以不花钱就体验相同的快感呢&#xff0c;答案是有的&#xff0c;下图中的平台就是这片文章看完操作完之后&#xff0c…

【JAVA进阶】File类、字节流

&#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;JAVASE基础 前言&#xff1a; 目前的编程中&#xff0c;数据存储方式有很多种&#xff0c;包括但不限于&#xff1a; 文件存储&#xff1a;将数据以文件的形式存储在磁盘上&#xff0c;可以使用文…

Radxa ROCK 5A 开箱

Rock5 Model A 是一款高性能的单板计算机&#xff0c;它采用了 RK3588S (8nm LP 制程&#xff09;处理器&#xff0c;具有 4 个高达2.4GHz 的 ARM Cortex-A76 CPU 核心、4 个高达 1.8GHz 的 Cortex-A55 内核和 Mali-G610 MP4 GPU。更重要的是&#xff0c;它还有一个高达 6TOPS …

内外网隔离下,通过网关转发,来部署前后端分离的系统

前言 最近为某银行系统部署了一套商城系统&#xff0c;网络环境比较特别&#xff0c;思路记录下&#xff0c;其中商场系统使用前后端分离模式部署。 该银行网络环境&#xff1a; 外网服务器&#xff1a;外网可以访问到它&#xff0c;不能访问外网。 网关服务器&#xff1a;跟…

横向移动-传递攻击atschtasks

横向移动就是拿下对方一台主机后&#xff0c;以拿下的那台主机作为跳板&#xff0c;对内网的其他主机再进行后渗透&#xff0c;拿到其他内网主机的权限的过程。叫做横向移动。横向移动的主要目的就是扩大战果。 传递攻击主要建立在明文和hash值获取基础上进行攻击。 at和scht…

【7 Vue3 – Composition API】

1 认识Composition API Options API的弊端 setup函数 2 setup函数的参数 3 setup简单使用 1 注意不再有响应式数据 要做到响应式数据需要在数据定义时使用ref包装数据,并且在使用时,使用value解包 2 注意template要使用的数据或者函数,必须要return 返回才能被使用 <templa…

拉格朗日松弛与拉格朗日分解 lagrangian relaxation

首先介绍下拉格朗日松弛的出发点&#xff0c;以及该方法所属的门类&#xff1b;再介绍下拉格朗日松弛法需要处理的难点和注意事项。 目录 1.拉格朗日松弛出发点 2.拉格朗日松弛所属分类 3.拉格朗日松弛 3.1 拉格朗日松弛&#xff08;松弛全部&#xff0c;转化为无约束问题…

【秒懂·云原生】微服务篇 —— Spring Cloud Commons:公共抽象

&#x1f50e;这里是【秒懂云原生】&#xff0c;关注我学习云原生不迷路 &#x1f44d;如果对你有帮助&#xff0c;给博主一个免费的点赞以示鼓励 欢迎各位&#x1f50e;点赞&#x1f44d;评论收藏⭐️ &#x1f440;专栏介绍 【秒懂云原生】 目前主要更新微服务&#xff0c;…

ClickHouse安装部署

—仅供学习 如有侵权 请联系删除– 一、下载 选择Tgz安装包安装 下载地址&#xff1a;Index of /clickhouse/tgz/ 选择stable目录下的安装包&#xff0c;采用21.9.4.35版本&#xff0c;分别是&#xff1a; [roothadoop08 resources]# ll 总用量 1023548 -rw-r--r--. 1 root …

JavaEE HTTP应用层协议

HTTP应用层协议 文章目录 JavaEE & HTTP应用层协议1. HTTP的报文协议格式1.1 fiddler介绍1.2 HTTP请求1.3 HTTP响应 2. HTTP请求与响应2.1 首行2.1.1 http方法2.1.2 URL2.1.3 版本号 2.2 header与空行2.2.1 Host2.2.2 Content-Type 与 Content-Length2.2.3 User-Agent&…

基于JavaWeb的事业单位公务员招考信息发布平台-考务考试报名系统

本文介绍了使用Java技术开发公务员招考信息发布平台的设计与实现过程&#xff0c;首先对实现该系统的技术进行分析&#xff0c;说明选择Java和MySQL数据库的必要性&#xff0c;然后对公务员招考信息发布平台的需求进行分析。并接着对系统进行设计&#xff0c;包括架构设计、功能…

用Python实现问卷星自动填写(超详细!!!)

用Python实现问卷星自动填写&#xff08;超详细&#xff01;&#xff01;&#xff01;&#xff09; 前言一、配置环境1.1安装依赖1.2安装驱动 二、实战处理2.1、引入库函数2.2、程序所需函数详解&#xff08;1&#xff09;自定义单选函数&#xff08;2&#xff09;自定义多选函…

基于STM32的DHT11温湿度测量

目录 1.简介 2.主要参数 3.引脚说明 4.注意事项 5.单总线协议 6.数据格式 7.工作时序 8.分模块编写程序 1.简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术&#xff0c;确保产品具有极高的可靠…