深入了解C read/write函数和cat命令实现

article/2025/10/24 18:43:46

1.文件描述符 文件描述符(file descriptor)通常是一个小的非负整数,内核用以 标识一个特定进程正在访问的文件。当内核打开一个现有文件或创建一 个新文件时,它都返回一个文件描述符。在读、写文件时,可以使用这 个文件描述符。

2.标准输入、标准输出和标准错误 按惯例,每当运行一个新程序时,所有的 shell 都为其打开 3 个文 件描述符,即标准输入(standard input)、标准输出(standard output) 以及标准错误(standard error)。如果不做特殊处理,例如就像简单的 命令ls,则这3个描述符都链接向终端。大多数shell都提供一种方法,使 其中任何一个或所有这3个描述符都能重新定向到某个文件,例如: ls > file.list 执行ls命令,其标准输出重新定向到名为file.list的文件。

3.不带缓冲的I/O 函数open、read、write、lseek以及close提供了不带缓冲的I/O。这些 函数都使用文件描述符。

1、read()

函数定义:ssize_t read(int fd, void * buf, size_t count);

函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。

返回值:返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据。若参数count 为0, 则read()不会有作用并返回0。另外,以下情况返回值小于count:
(1)读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有50个字节而请求读100个字节,则read返回50,下次read将返回0。
(2)对于网络套接字接口,返回值可能小于count,但这不是错误,详细解释参考这篇文章https://blog.csdn.net/hhhlizhao/article/details/73912578
注意:read时fd中的数据如果小于要读取的数据,就会引起阻塞。(关于read的阻塞情况网上有朋友有不同意见,笔者查阅资料后作如下补充。)以下情况read不会引起阻塞:

(1)常规文件不会阻塞,不管读到多少数据都会返回;

(2)从终端读不一定阻塞:如果从终端输入的数据没有换行符,调用read读终端设备会阻塞,其他情况下不阻塞;

(3)从网络设备读不一定阻塞:如果网络上没有接收到数据包,调用read会阻塞,除此之外读取的数值小于count也可能不阻塞,原因见上面链接。

由于笔者水平有限,如果文中有谬误之处还恳请诸位指出,以免误导大家。

2、write()
函数定义:ssize_t write (int fd, const void * buf, size_t count);

函数说明:write()会把参数buf所指的内存写入count个字节到所指的文件fd内。

返回值:如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。

附加说明:

(1)write()函数返回值一般无0,只有当如下情况发生时才会返回0:write(fd, buf, count)中第三参数为0,此时write()什么也不做,只返回0。

(2)write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。如可按如下格式实现读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。

(3)在write一次可以写的最大数据范围内(貌似是BUFSIZ ,8192),第三参数count大小最好为buf中数据的大小,以免出现错误。(经过笔者再次试验,write一次能够写入的并不只有8192这么多,笔者尝试一次写入81920000,结果也是可以,看来其一次最大写入数据并不是8192,但内核中确实有BUFSIZ这个参数,具体指什么还有待研究)

我们可以写一个简单的文件读写程序,实现从标准输入到标准输出echo(复读机)

#include "../all.h"
#include <unistd.h>
#define BUFFSIZE 4096int main(int argc, char* argv[]) {int n = 0;char buf[BUFFSIZE];printf("This is a simple read/write test\n");while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) {if(write(STDOUT_FILENO, buf, n)!=n) {printf("write error\n");}}if(n < 0) {printf("read error\n");}return 0;
}
4064394-3411706c61eb42ba.png
echo复读机

还可以打开文件,输出到标准输出 实现cat

#include "../all.h"
#include <fcntl.h>
#include <unistd.h>
#define BUFFSIZE 4096
int main(int argc, char* argv[]) {printf("this is a simple cat, will show the file\n");if(argc  < 2) {printf("argument not enough , at least 2\n");exit(-1);}char buf[BUFFSIZE];memset(buf,0,BUFFSIZE);int n =0;int fd = open(argv[1], O_RDWR|O_CREAT);while(true) {int len = 0;while((n= read(fd, buf,BUFFSIZE)) > 0) {if(write(STDOUT_FILENO,buf + len,n) !=n) {printf("write error\n");exit(-1);} len+=n;}break;}return 0;
}
4064394-07b564d373fbbb41.png
简单的cat

头文件<unistd.h>(apue.h中包含了此头文件)及两个常量 STDIN_FILENO和STDOUT_FILENO是POSIX标准的一部分(下一章 将对此做更多的说明)。头文件<unistd.h>包含了很多UNIX系统服务的 函数原型。

两个常量STDIN_FILENO和STDOUT_FILENO定义在<unistd.h>头 文件中,它们指定了标准输入和标准输出的文件描述符。在POSIX标准 中,它们的值分别是0和1,但是考虑到可读性,我们将使用这些名字来 表示这些常量。

将详细讨论BUFFSIZE常量,说明它的各种不同值将如何影响 程序的效率。但是不管该常量的值如何,此程序总能复制任一UNIX普 通文件。

4.标准I/O
read函数返回读取的字节数,此值用作要写的字节数。当到达输入 文件的尾端时,read返回0,程序停止执行。如果发生了一个读错误, read返回−1。出错时大多数系统函数返回−1。 标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接 口。使用标准I/O函数无需担心如何选取最佳的缓冲区大小。例如,fgets函数读取一个完整的 行,而read函数读取指定字节数。

我们最熟悉的标准I/O函数是printf。在调用printf的程序中,总是包 含<stdio.h>(在本书中,该头文件包含在apue.h中),该头文件包括了 所有标准I/O函数的原型。


http://chatgpt.dhexx.cn/article/HtffwgJe.shtml

相关文章

极路由最新刷机教程

本文参考&#xff1a;点击打开链接 前提条件 极路由1s、2、3、4&#xff0c;新老版本都可以&#xff0c;固件版本要求9006~9018。但实际上9019以及最新的1.0.xxx也都支持&#xff0c;只不过必须使用ss插件直达页面去操作ss&#xff0c;ss功能完美&#xff0c;就是界面有点简陋。…

极路由(极壹S)HC5661安装OpenWrt及救砖过程

极路由(极壹S)HC5661安装OpenWrt及救砖过程 文章目录 极路由(极壹S)HC5661安装OpenWrt及救砖过程1.免插件离线Root1.1 点击 获取local_token1.2 点击 获取uuid1.3 获取cloud token1.4 开启ssh1.5 永久开启ssh 2.刷不死uboot(breed)2.1 核对路由器型号2.2 下载breed固件2.3 刷入…

ssh登录极路由后台_OpenWrt刷机详细流程(极路由)

要想深入理解某个软件,首先熟悉其安装步骤,亲自感受软件的强大。OpenWrt是Linux的一个发行版,是一个独立的操作系统,主要运行在嵌入式设备中,由于嵌入式硬件种类繁多,并且稍微不慎就可能导致板子变砖,这给开发者带来了很大麻烦。 本篇文章以极路由为例,详细记录了OpenW…

浙大玉泉校区路由器L2TP设置(极路由1s)

我的宿舍里的ZJUWLAN信号太不稳定了&#xff0c;所以打算用有线。房间里只有一个有线口&#xff0c;还离的很远&#xff0c;所以打算连个路由器&#xff0c;然后用wifi连接。 步骤如下&#xff1a; 申请IP 浙江大学学生公寓服务网&#xff1a; http://service.chinasinew.co…

极路由云平台倒闭,路由器免插件离线ROOT方法

极路由云平台停服&#xff0c;离线root方法 免插件离线ROOT方法 访问&#xff1a;http://www.hiwifi.wtf/ 步骤 1. 点击 获取local_token 注意该网页不要关闭&#xff0c;后续获得 cloud token&#xff0c;填入并提交&#xff0c;即可临时获得ssh权限 即&#xff1a;http…

极路由1s HC5661 编程器救砖教程

说明&#xff1a;极1s如果刷错了固件&#xff0c;比如刷了HC5661A之类的&#xff0c;那么&#xff0c;会出现亮不灯的死机情况&#xff0c;这个时候说明固件引导已经刷坏了&#xff0c;只能拆机用编程器救砖或者返厂维修。如果采用编程器的话&#xff0c;因为没有备份&#xff…

极路由器1S,HC5661A刷breed再刷老毛子华硕

极路由器1S-HC5661A刷breed再刷华硕老毛子&#xff0c;再次编辑补充HC5661不带A的教程 特别提醒&#xff1a; 本教程是教授大家如何对【极路由器1S&#xff0c;HC5661A】以及【hc5661不带A的】进行刷机&#xff0c;载入breed并刷入华硕老毛子固件&#xff08;以下简称老毛子&a…

更新极路由器1S,HC5661A刷breed再刷老毛子华硕教程

更新极路由器1S-HC5661A刷breed再刷老毛子老毛子教程&#xff0c;再次编辑附加HC5661不带A的 特别提醒&#xff1a; 2021年1月1日起&#xff0c;极路由器官网www.hiwifi.com域名到期&#xff0c;云平台正式关闭&#xff0c;之前我发布的极1S刷机教程是基于云平台获取root权限的…

极路由刷个人编译的openwrt固件全过程

说明 以下是极1s刷机的整个流程&#xff0c;包括openwrt 极路由固件的编译和升级流程&#xff0c;主要是为了方便发烧友或者开发人员。 准备工作 极壹S(型号HC5661)一台 串口板和串口线(如果是高级玩家) 电脑、网线等软件(vmware、tftpd、linux编译环境) 网络配置 极路由为…

极1s刷Padavan改华硕[N14U N54U]固件

打开极路由的开发者模式 打开开发者模式 登陆极路由的后台管理界面&#xff0c;点击云插件&#xff0c;进入到极路由云插件管理后点击路由信息&#xff0c;然后在最下面点击开通开发者模式&#xff0c;这里需要你放弃极路由的保修以及安装APP等一系列的工作&#xff0c;大家照…

在极路由极1S上使用entware

目录 打开ssh功能安装entware使用感想备份和还原entware注意程序开启启动参考文章 本想在极1S上安装些程序&#xff0c;结果登录ssh后发现系统自带的opkg有限制&#xff0c;即使更改为openWRT的源也不能安装&#xff0c;说各种不兼容。于是打算装entware。 entware是面向 Linux…

Drcom下如何使用路由器上校园网并开启WIFI(以广东工业大学、极路由1S HC5661A为例)

免责声明&#xff1a; 在根据本教程进行实际操作时&#xff0c;如因您操作失误导致出现的一切意外&#xff0c;包括但不限于路由器变砖、故障、数据丢失等情况&#xff0c;概不负责&#xff1b;该技术仅供学习交流&#xff0c;请勿将此技术应用于任何商业行为&#xff0c;所产生…

极路由1S HC5661A 刷入不死u-boot(breed)加刷潘多拉固件教程

原文来自&#xff1a;新版极路由1S&#xff08;HC5661A&#xff09;刷潘多拉加SS配置教程 不死uboot(breed)如何使用 下文是以原文为基础&#xff0c;更详细也更适合小白的整合版。 注意&#xff1a;本贴是新版的白盒极路由1S&#xff08;HC5661A&#xff09;教程&#xff…

极路由s1有wds_极路由1、1s等机型刷OpenWrt--成为真正的极客

0x00&#xff1a;我为什么买极路由 买极路由的时候&#xff0c;他们说这是个给极客打造的智能路由&#xff0c;一开始还因为国际版&#xff0c;被gov直接请去喝茶了。 当时觉得&#xff0c;这玩意能给APPStore加速&#xff0c;还能屏蔽广告&#xff0c;简直NB。那时候也没啥钱&…

极路由1S 开启临时ssh 并刷breed成功

手上有一台别人给的 极路由1s&#xff0c;刷的是不知名版本的openwrt版本&#xff0c;也无法远程ssh&#xff0c;也就无法刷新的固件玩玩。 以前没接触过软路由和路由系统&#xff0c;找了很多资料&#xff0c;都没法正常获取ssh权限。 折腾了一两天&#xff0c;结果发现我刷的…

极路由 刷linux,记一次 极路由1S HC5661 TTL root 刷 U-BOOT 不死固件 及 爱快固件-20200320更新...

18.png (15.32 KB, 下载次数: 8) 2016-7-14 16:55 上传 2、用PUTTY的SSH类型登陆192.168.199.1,端口号:22。login as输入root,password输入admin。 备份原厂固件,需要插入SD卡(不需要刷回原厂固件的就直接略过吧):root@Hiwifi:/#cat/proc/mtd #列出路由器分区情况m…

极路由 刷linux,极路由1s刷openwrt不完全教程

极路由是基于openwrt做的二次开发。cpu是mtk7620a属于mips架构。 如果对svn和编译比较熟悉的话&#xff0c;可以获取官方的源码&#xff0c;自行编译。 如果对这些一窍不通的话&#xff0c;建议安装我下面提供的教程一步步操作。 1&#xff0c;首先看你的极路由版本。如果是开发…

极路由1S刷openwrt

文章目录 准备材料刷机流程 准备材料 breed下载,选择5661a的 https://breed.hackpascal.net/ openwrt固件 选择76x8版本的openwrt固件 https://downloads.openwrt.org/releases/21.02.0-rc3/targets/ramips/mt76x8/ 刷机流程 进入极路由1s root模式 解锁root可参考链接&…

极路由1S HC5661A 刷入不死u-boot和Openwrt

开通开发者模式 192.168.199.1&#xff0c;进入路由器后台&#xff0c;点击智能插件&#xff0c;然后选择中由器信息&#xff0c;再点高级设置 开启开发者模式后&#xff0c;记录 SSH 登录信息 进入路由器后台 安装Shell工具&#xff0c;Windows上有 putty 和XShell等等&a…

极路由1S升级系统之后再刷机学习记录

一、升级极路由1S固件 学习的是这位博主的教程&#xff1a;https://blog.csdn.net/qq_39257487/article/details/114867431 极路由器1S&#xff0c;HC5661A固件下载&#xff08;免费获取&#xff09;&#xff1a;下载地址 第2步&#xff0c;右击右下角的网络图---->打开网…