无缓冲区的I/O操作

文件描述符

文件描述符是一个非负的小整数,当我们创建或者打开文件时,内核便会返回一个文件描述符,来标识这个打开或者创建的文件。

标准输入,标准输出,标准错误

当我们开启一个进程时会自动打开这三个描述符,STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO这三个宏定义的描述符分别为0,1,2。这些通常是在unistd.h中定义的。我们可以通过这些描述符进行从终端来进行输入输出操作。

#include<stdio.h>
#include<unistd.h>
int main()
{
char a[10];
read(STDIN_FILENO,a,10);
write(STDOUT_FILENO,a,20);
}

无缓冲的函数

我们这节主要介绍的是无缓冲的I/O函数,无缓冲表示这些函数都是系统调用,我们在讨论原子的操作的时候无缓冲的函数是很重要的。

  • read函数
  • write函数
  • open函数
  • lseek函数
  • close函数

open函数

函数原型

#include<fcntl.h>
int open(const char *path,int oflag /, mode_t mode/);
  • 这个函数的作用便是打开一个文件,若成功返回文件描述符,错误返回-1。
  • 第一个参数表示文件的路径,第二个参数表示文件的打开方式,第三个函数是可选的。
  • 我们介绍一下第二个参数的宏定义
  • 只能选一个
  • O_WRONLY 表示文件以只读的方式打开
  • O_RDONLY 表示文件以只写的方式打开
  • O_RDWR 表示文件以读写的方式打开
  • 可以选多个
  • O_APPEND 表示将读写指针移动到最后,将写入的内容添加到文件末尾,如果- 直接写会覆盖原来的内容。
  • O_CREAT 当使用这个时,必须有第三个参数。表示创建一个文件。
  • O_NONBLOCK 表示将此文件以非阻塞的方式打开。
  • O_TRUNC 这个参数表示将文件读写指针阶段为0
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fp = open("aa.txt",O_WRONLY|O_APPEND);
char a[10]="dsdsdfs";
write(fp,a,strlen(a));
printf("%s",a);
}
测试:
root@ubuntu:/home/sun/project# cat aa.txt
dsjfskjfsds
fdssdjk

dsdsdfs
dsdsdfs111111root@ubuntu:/home/sun/project# 
将内容添加到文件末尾

read函数

函数原型

#include<unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes);
  • 第一个参数表示文件描述符,第二个参数表示任意类型的缓冲区,第三个参数表示一个无符号整形数。
  • 这个函数的返回值类型为有符号整形,因为如果出错返回-1,所以是有符号的,正常情况下返回读到字符的个数,当达到文件结尾时返回0。
  • 这个函数读取字符时会将换行符也读取出来,比如我们有两行数据,我们可以一次性读取出来。
  • 但是当从终端读取时只能读取一行
  • 有一些情况会出现读取的字符数小于我们要求的字符数。
  • 当我们要求读取100个时,但是文件里只有30个,便会读取30个,返回30,当下次再读取时便会返回0。
  • 当我们从终端读取时,每次只能读取一行,可能会少于我们的要求。
  • 当我们从网络中读取时可能会少于我们的要求。
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
char a[100];
read(STDIN_FILENO,a,10);
printf("%s",a);
}

测试:
root@ubuntu:/home/sun/project# ./test
gfdjhskjalksaldsasfjediskkasjdkdndfcska
gfdjhskjal<root@ubuntu:/home/sun/project# ksaldsasfjediskkasjdkdndfcska
ksaldsasfjediskkasjdkdndfcska: command not found
可以看到当我们输入的字符数大于读取的字符数时,只是读取了我们要求的字符数10,剩余的字符数没有被读取。我们可以将我们从终端的输入看作是一个文件,read函数从终端这个文件中读取指定数目的字符。
eg:
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
char a[10];
read(STDIN_FILENO,a,20);
printf("%s",a);
}
测试:
root@ubuntu:/home/sun/project# ./test
1234567890122345
1234567890122345
�Fl�root@ubuntu:/home/sun/project# 
可以看到当我们输入的字符数大于我们的缓冲区时便会出现错误。

write函数

函数原型

#include<unistd.h>
ssize_t write(int fd,const void *buf,size_t nbytes);
  • 这个函数表示向一个文件中写入字符。
  • 成功返回写入的字符数,失败返回-1。
  • 当写入时文件的读写指针会做出相应的偏移。

close函数

这个函数表示关闭打开的文件

lseek函数

每打开一个文件便会返回一个文件描述符,但是内核会维护一个文件偏移量,正常打开文件文件偏移量为0,但是当我们使用O_APPEND时便会将文件偏移量指向最后一个字符,我们的读写操作都是从文件偏移量的位置开始的,当我们读取或写入一个字节,文件的偏移量也会增加1,lseek这个函数便是来操作文件偏移量的,可以使用lseek函数来操作我们想要从任意位置的读写位置。

函数原型

#include<unistd.h>
off_t lseek(int fd,off_t offset,int whence)
返回值:成功返回文件的新的偏移量,失败返回-1

参数解释

  • 第一个参数表示文件描述符
  • 第二个参数表示文件的相对偏移
  • 第三个参数为SEEK_SET,将文件偏移量设置为距离文件开头offset个字节
  • 第三个参数为SEEK_CUR,将文件偏移量设置为距离现在的偏移量的offset个字节
  • 第三个参数为SEEK_END,将文件偏移量设置为文件长度加offset
  • 这个函数只能对普通的文件设置文件偏移量,不能对管道 FIFO 网络套接字设置偏移量
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
int main()
{
int fd=open("aa.txt",O_RDONLY);
int a=lseek(fd,2,SEEK_SET);
char buf[10];
read(fd,buf,10);
printf("%d     %s",a,buf);

}

文件共享

我们可以在多个进程之间打开同一个文件,我们将介绍多个进程同时操作同一个文件时相互产生的影响。

20130912202531765.png
  • 每个进程在进程表中都有一个记录,这个记录中包含这个进程打开的文件,记录文件描述符标志和文件表项的指针。
  • 文件表项包含文件状态标志(读写和是否阻塞等),当前偏移量
    和v节点的指针。
  • v节点和i节点包含文件一些信息,文件的当前长度,文件的所有者等信息。
    上面这个图便是当一个进程两次打开同一个文件时的情况,每个文件描述符都有自己的文件表项,因此每个文件描述符可能有不同的读写或者是否阻塞和不同的偏移量等信息,但是这两个文件描述符一个共同的v和i节点,因此他们的所有者和文件的长度等信息是共享的,我们可以知道lseek函数作用的便是文件表项的当前偏移量,当我们使用这两个文件描述符进行都操作时是没有相互影响的,但是当我们同时对这个文件进行写操作时是有影响的,因此我们接下来便开始讲解进行写操作时相互的影响。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,820评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,648评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,324评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,714评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,724评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,328评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,897评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,804评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,345评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,431评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,561评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,238评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,928评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,417评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,528评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,983评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,573评论 2 359