【Linux操作系统】深入理解系统调用中的read和write函数

在操作系统中,系统调用是用户程序与操作系统之间进行交互的重要方式。其中,read和write函数是常用的系统调用函数,用于在用户程序和操作系统之间进行数据的读取和写入。本文将深入介绍read和write函数的工作原理、用法以及示例代码,以帮助读者更好地理解和应用这两个函数。
在这里插入图片描述

文章目录

    • 1. read函数的工作原理及用法:
      • 1.1 函数原型和参数
      • 1.2 代码举例
      • 1.3 代码解释
    • 2. write函数的工作原理及用法:
      • 2.1 函数原型和参数
      • 2.2 代码举例
      • 2.3代码解释
    • 3. 文件描述符
      • 3.1 进程控制块
      • 3.2 什么是文件操作符
      • 3.3 特殊的文件描述符

1. read函数的工作原理及用法:

1.1 函数原型和参数

read函数用于从文件描述符中读取数据,并将数据存储到缓冲区中。

其函数原型如下:

ssize_t read(int fd, void *buf, size_t count);

其中,fd是文件描述符,buf是存放读取数据的缓冲区,count是要读取的字节数。read函数返回实际读取的字节数,如果返回 -1 表示读取失败。

官方手册的解释:
 
在这里插入图片描述

1.2 代码举例

下面是一个使用read函数从文件中读取数据的示例代码:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("file.txt", O_RDONLY);char buffer[1024];ssize_t bytesRead = read(fd, buffer, sizeof(buffer));if (bytesRead == -1) {perror("read");return 1;}printf("Read %ld bytes: %s\n", bytesRead, buffer);close(fd);return 0;
}

1.3 代码解释

在上述示例代码中,首先使用open函数打开一个名为file.txt的文件,并以只读方式打开。然后,read函数从文件中读取数据,并将数据存储到buffer中,最后通过printf函数输出读取的数据。

2. write函数的工作原理及用法:

2.1 函数原型和参数

write函数用于将数据从缓冲区写入到文件描述符中。

其函数原型如下:

ssize_t write(int fd, const void *buf, size_t count);

其中,fd是文件描述符,buf是存放待写入数据的缓冲区,count是要写入的字节数。write函数返回实际写入的字节数,如果返回 -1 表示写入失败。

官方手册的解释:

在这里插入图片描述

2.2 代码举例

下面是一个使用write函数将数据写入文件的示例代码:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("file.txt", O_WRONLY | O_CREAT, 0644);char *data = "Hello, world!";ssize_t bytesWritten = write(fd, data, strlen(data));if (bytesWritten == -1) {perror("write");return 1;}printf("Written %ld bytes\n", bytesWritten);close(fd);return 0;
}

2.3代码解释

在上述示例代码中,首先使用open函数创建一个名为file.txt的文件,并以只写方式打开。然后,write函数将字符串"Hello, world!"写入到文件中,最后通过printf函数输出写入的字节数。

3. 文件描述符

3.1 进程控制块

进程控制块(Process Control Block,PCB)是操作系统中用于管理和控制进程的数据结构。每个正在运行或等待运行的进程都有一个对应的PCB,它包含了进程的各种属性和状态信息。

PCB通常是一个数据结构,其中包含了以下信息:

  1. 进程标识符(Process Identifier,PID):用于唯一标识一个进程。
  2. 程序计数器(Program Counter,PC):记录了下一条要执行的指令的地址。
  3. 寄存器集合:包括通用寄存器、指令寄存器、栈指针等,用于保存进程的上下文信息。
  4. 进程状态(Process State):表示进程的当前状态,如运行、就绪、等待等。
  5. 进程优先级(Process Priority):用于确定进程在调度时的优先级顺序。
  6. 进程调度信息:包括进程的调度策略、时间片大小等。
  7. 进程资源管理信息:包括进程所拥有的资源、打开的文件等。
  8. 父进程标识符(Parent Process Identifier,PPID):记录了创建该进程的父进程的PID。
  9. 进程创建时间和运行时间:记录了进程的创建时间和运行时间。
  10. 内存管理信息:包括进程的内存分配情况、页面表等。
  11. 文件描述符表:记录了进程打开的文件和对应的文件描述符。

PCB是操作系统中非常重要的数据结构,它存储了进程的所有关键信息,使得操作系统能够对进程进行管理和调度。当操作系统需要切换进程时,会保存当前进程的上下文信息到其对应的PCB中,并加载下一个进程的上下文信息。这样可以实现进程的切换和并发执行。

3.2 什么是文件操作符

文件描述符可以被看作是操作系统为了管理打开的文件或设备而分配的一个标识符。它是一个整数值,用于标识一个特定的文件或设备。

想象一下,你在操作系统中打开了一个文件或设备,比如一个文本文件或一个串口设备。操作系统会为这个文件或设备分配一个文件描述符,并将其返回给你。这个文件描述符就像是一个门牌号,用于标记这个文件或设备

当你想对这个文件或设备进行读取写入关闭等操作时,你只需要告诉操作系统使用这个文件描述符,操作系统就会知道你要操作的是哪个文件或设备。

文件描述符的具体值是一个非负整数,通常从0开始递增。操作系统会使用一个文件描述符表来记录所有打开的文件或设备的信息,包括文件的位置、读写权限等。当你使用文件描述符进行操作时,操作系统会根据文件描述符找到对应的文件信息,并执行相应的操作。

在这里插入图片描述

3.3 特殊的文件描述符

  1. 标准输入(Standard Input,STDIN):标准输入文件描述符,通常用整数值0表示;在C语言中,可以使用宏定义STDIN_FILENO来表示标准输入。它用于接收用户的输入,比如键盘输入。
#include <unistd.h>int main() {char buffer[100];ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer));// 从标准输入读取数据// ...return 0;
}
  1. 标准输出(Standard Output,STDOUT):通常用整数值1来表示。在C语言中,可以使用宏定义STDOUT_FILENO来表示标准输出。它用于向屏幕或终端输出信息。
#include <unistd.h>int main() {char buffer[] = "Hello, World!";ssize_t bytesWritten = write(STDOUT_FILENO, buffer, sizeof(buffer));// 将数据输出到标准输出// ...return 0;
}
  1. 标准输入(Standard Input,STDIN):通常用整数值2来表示。在C语言中,可以使用宏定义STDERR_FILENO来表示标准错误。它用于接收用户的输入,比如键盘输入。
#include <unistd.h>
#include <stdio.h>int main() {fprintf(stderr, "An error occurred!\n");// 输出错误信息到标准错误// ...return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot异步任务

在Service类声明一个注解Async作为异步方法的标识 package com.qf.sping09test.service;import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;Service public class AsyncService {//告诉spring这是一个异步的方法Asyncp…

使用gpt对对话数据进行扩增,对话数据扩增,数据增强

我们知道一个问题可以使用很多方式问&#xff0c;但都可以使用完全一样的回答&#xff0c;基于这个思路&#xff0c;我们可以很快的扩增我们的数据集。思路就是使用chatgpt或者gpt4生成类似问题&#xff0c;如下&#xff1a; 然后我们可以工程化这个过程&#xff0c;从而快速扩…

【Github】SourceTree技巧汇总

sourceTree登录github账户 会跳转到浏览器端 按照Git Flow 初始化仓库分支 克隆远程仓库到本地 推送变更到远程仓库 合并分支 可以看到目前的本地分支&#xff08;main、iOS_JS&#xff09;和远程分支&#xff08;origin/main、origin/HEAD、origin/iOS_JS&#xff09;目前所处…

【问题记录】antd icons报rev属性缺失错误

闲来无事将项目中的antd从v4升级到了v5&#xff0c;之前正常的页面中如有图标&#xff0c;如<PlusOutlined />&#xff0c;总是报以下错误&#xff1a; TS2741: Property rev is missing in type {} but required in type Pick<AntdIconProps, "name" …

如何实现Vue路由的二级菜单

目录 Vue路由&#xff08;一、二级路由&#xff09; 一级路由配置 二级路由配置 Vue中展示二级路由的默认模块/二级路由默认显示 Vue路由&#xff0c;二级路由及跳转 如何用vue实现二级菜单栏 ◼️ 相关参考资料 当朋友们看到这个文章时想必是想要了解vue路由二级菜单相…

React UI组件库

1 流行的开源React UI组件库 1 material-ui(国外) 官网: Material UI: React components based on Material Design github: GitHub - mui/material-ui: MUI Core: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Go…

人大金仓助力某大型金融机构业务系统异地容灾优化升级

日前&#xff0c;人大金仓助力某大型金融机构应收账款融资服务平台异地容灾项目顺利上线&#xff0c;保证了平台系统运行的连续性和数据安全&#xff0c;为充分发挥平台的融资功能&#xff0c;缓解中小微企业融资难提供了强有力的保障。 “ 缓解中小微企业融资难 某大型金融机构…

Stephen Wolfram:意义空间和语义运动规律

Meaning Space and Semantic Laws of Motion 意义空间和语义运动规律 We discussed above that inside ChatGPT any piece of text is effectively represented by an array of numbers that we can think of as coordinates of a point in some kind of “linguistic feature …

【第二阶段】在函数中定义参数是函数的函数

1.理解&#xff1a;在一个函数中有一个参数a,这个参数a又属于一个函数&#xff0c;a即时参数又是函数 2.用kotlin实现登录 /*** You can edit, run, and share this code.* play.kotlinlang.org*/ fun main() {//调用传参//普通参数传入即可,针对在调用函数中的参数函数传入使用…

Android Studio实现Spinner下拉列表

效果图 点击下拉列表 点击某一个下拉列表 MainActivity package com.example.spinneradapterpro;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Spinn…

关于使用pycharm遇到只能使用unittest方式运行,无法直接选择Run

相信大家可能都遇到过这个问题&#xff0c;使用pycharm直接运行脚本的时候&#xff0c;只能选择unittest的方式&#xff0c;能愁死个人 经过几次各种尝试无果之后&#xff0c;博主就放弃死磕了&#xff0c;原谅博主是个菜鸟 后来遇到这样的问题&#xff0c;往往也就直接使用cm…

差分升级在物联网水表上的实现与应用(学习)

摘要 当越来越多的物联网水表加入抄表系统后&#xff0c;实现了水表数据的信息化&#xff0c;并且当水表终端需要技术更新时&#xff0c;通过网络方式来升级产品可以高效修复设备面临的问题&#xff0c;减少用户损失&#xff0c;降低维护成本&#xff0c;但同时也对有限的网络…

HCIP VRRP技术

一、VRRP概述 VRRP&#xff08;Virtual Router Pedundancy Protocol&#xff09;虚拟路由器冗余协议&#xff0c;既能够实现网关的备份&#xff0c;又能够解决多个网关之间互相冲突的问题&#xff0c;从而提高网络可靠性。 局域网中的用户的终端通常采用配置一个默认网关的形…

Leetcode-每日一题【剑指 Offer 12. 矩阵中的路径】

题目 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 例如&#xff0c;在下面的 34 的矩阵中包含单词 "ABCCED"&#xff08;单词中的字母…

f1tenth仿真设置

文章目录 一、安装依赖二、进入工作空间克隆三、编译四、运行 一、安装依赖 tf2_geometry_msgs ackermann_msgs joy map_server sudo apt-get install ros-noetic-tf2-geometry-msgs ros-noetic-ackermann-msgs ros-melodic-joy ros-noetic-map-server 二、进入工作空间克隆…

数据结构刷题训练:设计循环队列(力扣OJ)

目录 文章目录 前言 1. 题目&#xff1a;设计循环队列 2. 思路 3. 分析 3.1 定义循环队列 3.2 创建队列 3.3 判空和判满 3.4 入队 3.5 出队 3.6 取队头队尾数据 3.7 销毁队列 4. 题解 总结 前言 当谈到队列数据结构时&#xff0c;很多人可能会想到普通的队列&#xff0c;即先进…

Python-OpenCV中的图像处理-霍夫变换

Python-OpenCV中的图像处理-霍夫变换 霍夫变换霍夫直线变换霍夫圆环变换 霍夫变换 霍夫(Hough)变换在检测各种形状的技术中非常流行&#xff0c;如果要检测的形状可以用数学表达式描述&#xff0c;就可以是使用霍夫变换检测它。即使要检测的形状存在一点破坏或者扭曲也是可以使…

ThinkPHP8命名规范-ThinkPHP8知识详解

本文主要讲解thinkphp8的命名规范&#xff0c;主要包括&#xff1a;遵循PHP自身的PSR-2命名规范和PSR-4自动加载规范、目录和文件命名规范、函数和类、属性命名规范、常量和配置命名规范、数据表和字段命名规范、不能使用PHP保留字。 在使用thinkphp8开发项目之前&#xff0c;…

Docker安装ElasticSearch/ES 7.4.0

目录 前言安装ElasticSearch/ES安装步骤1&#xff1a;准备1. 安装docker2. 搜索可以使用的镜像。3. 也可从docker hub上搜索镜像。4. 选择合适的redis镜像。 安装步骤2&#xff1a;拉取ElasticSearch镜像1 拉取镜像2 查看已拉取的镜像 安装步骤3&#xff1a;创建容器创建容器方…