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

news2024/10/7 14:27:43

在操作系统中,系统调用是用户程序与操作系统之间进行交互的重要方式。其中,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.coloradmin.cn/o/870775.html

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

相关文章

chatGPT小白快速入门-002:一文看懂什么是chatGPT

一、前言 本文是《chatGPT小白快速入门培训课程》的第002篇文章&#xff1a;一文看懂什么是chatGPT&#xff0c;全部内容采用chatGPT和chatGPT开源平替软件生成。完整内容大纲详见&#xff1a;《chatGPT小白快速入门课程大纲》。 本系列文章&#xff0c;参与&#xff1a; AIGC…

对doccano自动标注使用的默认UIE模型进行微调以提高特定领域的实体识别能力,提高标注速度

预处理doccano标注的数据 该章节详细说明如何通过doccano.py脚本对doccano平台导出的标注数据进行转换&#xff0c;一键生成训练/验证/测试集。 在本地部署UIE模型 下载模型压缩包&#xff1a; 本来是要通过一定的方法&#xff08;GitZip&#xff09;才能在整体的大项目仓库…

C++初阶之一篇文章教会你list(模拟实现)

list&#xff08;模拟实现&#xff09; list模拟实现list_node节点结构定义std::__reverse_iterator逆向迭代器实现list迭代器 __list_iterator定义list类成员定义list成员函数定义1.begin()、end()、rbegin()和rend()2.empty_init()3.构造函数定义4.swap5.析构函数定义6.clear…

HCIP BGP 实验

​​​​​​​ 拓扑图 r1: <Huawei>sys [Huawei]sys r1 [r1]int g 0/0/1 [r1-GigabitEthernet0/0/1]ip add 12.1.1.1 24 [r1-GigabitEthernet0/0/1]int lo0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]ospf network-type broadcast [r1-bgp]peer 12.1.1.2 as-nu…

Spring Cloud 面试突击2

Spring Cloud 面试突击2 高并发&#xff1a;是一种系统运行过程中遇到的短时间大量的请求操作 响应时间&#xff1a; 吞吐量&#xff1a; QPS&#xff1a;数据库为维度 TPS 并发用户数 并发的维度&#xff1a;很多的 并发是不是达到的当前系统的瓶颈 缓存 &#xff08…

SpingBoot-Vue前后端——实现CRUD

目录​​​​​​​ 一、实例需求 ⚽ 二、代码实现 &#x1f3cc; 数据库 &#x1f440; 后端实现 &#x1f4eb; 前端实现 &#x1f331; 三、源码下载 &#x1f44b; 一、实例需求 ⚽ 实现一个简单的CRUD&#xff0c;包含前后端交互。 二、代码实现 &#x1f3cc; 数…

阶梯费用计算(配置化_最小demo)

本文旨在提供一种配置化思路计算阶梯费用&#xff0c;更高级的做法则是通过数据库配置&#xff0c;注册中心等&#xff1b;在表达式上可以采用自定义或者spel表达式等其他方式进行处理&#xff1b;(代码仅展示最小demo,部分不完善地方自行补充) 思路&#xff1a;N个区间对应N个…

重置mariadb数据库密码

使用场景重置步骤 重置数据库root用户密码为空重置数据库密码 文档暂时只支持未开启ha时manager使用的mariadb&#xff0c;开启ha的txsql和kundb类似&#xff0c;my.cnf文件地址和登录数据库命令不同 使用场景 manager数据库密码是通过调用接口并根据db.properties文件获取的…

众和转债,宏微转债,阳谷转债上市价格预测

众和转债 基本信息 转债名称&#xff1a;众和转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;13.75亿元。 正股名称&#xff1a;新疆众和&#xff0c;今日收盘价&#xff1a;8.14元&#xff0c;转股价格&#xff1a;8.2元。 当前转股价值 转债面值 / 转股…

基于SqlSugar的开发框架循序渐进介绍-- 快速构建系统参数管理界面

在参照一些行业系统软件的时候&#xff0c;发现一个做的挺不错的系统功能-系统参数管理&#xff0c;相当于把任何一个基础的系统参数碎片化进行管理&#xff0c;每次可以读取一个值进行管理&#xff0c;这样有利于我们快速的处理业务需求&#xff0c;是一个挺好的功能。本篇随笔…

【FastColoredTextBox】C# 开源文本编辑控件

主界面截图 使用Demos演示 FastColoredTextBox 是一个用于在 C# 程序中实现高亮语法着色、代码编辑和文本显示的自定义控件。它提供了许多功能&#xff0c;包括&#xff1a; 语法高亮&#xff1a;FastColoredTextBox 支持多种语言的语法高亮&#xff0c;可以根据语法规则将不同…

Linux 终端操作命令(2)内部命令

Linux 终端操作命令 也称Shell命令&#xff0c;是用户与操作系统内核进行交互的命令解释器&#xff0c;它接收用户输入的命令并将其传递给操作系统进行执行&#xff0c;可分为内部命令和外部命令。内部命令是Shell程序的一部分&#xff0c;而外部命令是独立于Shell的可执行程序…

32 | 全球新冠肺炎确诊病例趋势分析

任务背景 过去一年多的时间,对我们影响最大的事件就是全球新冠肺炎的大流行。新冠肺炎除了对患者带来痛苦之外,对医疗系统也带来了巨大的挑战。许多患者陷入危险的本质原因就是医疗资源的紧张,如果可以根据现有确诊的数据来预测将来可能的确诊数,那政府和医院就能够提前对…

【python可视化】爬取豆瓣电影Top250(附源码)

前言 在网络爬虫的开发过程中&#xff0c;经常会遇到需要处理一些反爬机制的情况。其中之一就是网站对于频繁访问的限制&#xff0c;即IP封禁。为了绕过这种限制&#xff0c;我们可以使用代理IP来动态改变请求的来源IP地址。在本篇博客中&#xff0c;将介绍如何使用代理IP的技术…

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

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

Leetcode34 在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 代码&#xff1a; c…

SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP

SpringBoot第35讲&#xff1a;SpringBoot集成连接池 - 默认连接池HikariCP 本文是SpringBoot第35讲&#xff0c;主要介绍数据库连接池&#xff0c;以及SpringBoot集成默认的HikariCP的实践。 文章目录 SpringBoot第35讲&#xff1a;SpringBoot集成连接池 - 默认连接池HikariCP1…

【STM32】简介

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星T…

Exploiting Proximity-Aware Tasks for Embodied Social Navigation 论文阅读

论文信息 题目&#xff1a;Exploiting Proximity-Aware Tasks for Embodied Social Navigation 作者&#xff1a;Enrico Cancelli&#xff0c; Tommaso Campari 来源&#xff1a;arXiv 时间&#xff1a;2023 Abstract 学习如何在封闭且空间受限的室内环境中在人类之间导航&a…

StarGANv2: Diverse Image Synthesis for Multiple Domains论文解读及实现

StarGAN v2: Diverse Image Synthesis for Multiple Domainsp github:https://github.com/clovaai/stargan-v2 0 小结 0.1 模型 4个 模型四个&#xff1a; Generator&#xff1a; G网络 输入图片x&#xff0c;和风格编码s&#xff08;可以是F网络或者E网络生成的s&#xff…