系统io,write read,重定向open,lseek(SEEK_SET,SEEKCUR,SEEKEND)

/*
区别与c语言中的文件IO:只能向普通文件内进行输入和输出,lsd中的文件io,他可以向任何类型的文件进行输入和输出操作。
由于linux中万物皆文件,包括运行中的两个程序也是两个文件,我们就可以通过lsd中的文件io向运行中的两个程序写入信息来达到数据通讯的效果。
/
/

lsd中文件io的一组函数 : read 和 write
函数名: write
头文件:sys/type.h,unistd
函数参数:int fd,const void* buf,size_t size
buf:存放有任意类型数据的地址
size:size_t 这样的数据我们可以看做是一个int,但是他其实是一个无符号整型,来保证数据绝对不会为负数。buf所存放的数据的字节数
fd:文件描述符,用来全权代表一个文件
c语言的文件io中,文件描述符是一个FILE的指针,用来指向文件在内存中的地址。
由于linux中所有的文件,都会将自己的地址存放在内存之中,这段内存我们自然可以看成一个数组,既然是数组,我们就可以通过下标的形式访问数组中的值,这个数组中的值就是一个文件的地址。
所以 fd 本质上就是一个存放了文件地址的数组的下标。
类似于fwrite/fread中代表了标准输入流,标准输出流和标准错误流的文件描述符分别为:stdin,stdout,stderr
write/read中代表标准输入流,标准输出流和标准错误流的文件描述符分别为:0,1,2
当然,为了提高代码的可读性,系统专门有3个宏来代表终端上的3个标准流,分别为:STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO,这3个宏的定义在头文件unistd.h中
因为以上3个标准流的存在,之后任意打开的文件,他的文件描述符总是从3开始。
函数名:read
头文件:unistd.h
函数参数:int fd,const char
buf,size_t size
返回值:成功读取到内容之后,返回读取到的内容的字节数,注意不是第三个参数,size代表最多读取size个字节,而返回值是实际读取到的字节数量。读取完成的话,会返回0,读取失败返回-1
read作为一个能够读取任意文件的函数,他会有多种行为模式
① 正常读取过程
② 失败读取:分为两种情况
当没有数据可读的时候,read将会阻塞
当没有数据可读的时候,并且将read设置成非阻塞模式,那么此时,read将会返回-1或者0(依据具体情况而定)。例如管道和套接字这种保持常连接的文件通讯桥梁,如果桥梁中断,read肯定返回-1
如何将read设置成非阻塞模式:两种方式
① 在打开文件的时候,直接以非阻塞模式打开
② 像stdin这种已经存在的文件,则只能通过获取文件属性,然后在添加非阻塞属性(使用按位或来添加)
/
/

那么如何打开一个lsd文件io中的文件:使用函数open
函数名:open
头文件:sys/type.h , sys/stat.h , fcntl.h
函数参数:const char* pathname,int mode,int access
pathname:想要打开的文件名
mode:以何种方式打开
open和fopen最大的区别就在于,fopen只要确定到底是"r"系列还是"w"系列,就能明确这个文件到时是否创建或者是否清空
但是open在明确到时是读取还是写入还是可读可写的时候,并不会明确到时是否创建文件或者清空文件内容,这些操作全都需要自己传入参数来确定
我们来看一下mode有哪些属性:
O_RDONLY:只读的方式打开,打开后光标在文件的最开头
O_WRONLY:只写的方式打开,打开后光标在文件的最末尾
O_CREAT:如果文件不存在,则创建文件
O_EXCL:如果想要创建的文件已经存在,则open返回-1,并且修改标准错误流中的错误标识符
O_TRUNC:如果想要创建的文件已经存在,则清空文件后打开
O_NONBLOCK:以非阻塞的形式,打开一个文件,打开后,使用read读取该文件,就会是非阻塞模式
access:这是一个可变参数,如果文件不存在,并且mode中拥有创建文件的行为的话,则需要传入access来确定以何种权限来创建该文件,自然这里的access就是我们之前接触到的4,2,1,并且是3组人的权限,但是一定要注意的时候,这里的权限是一个八进制的整型数,所以传参的时候,例如满权限创建文件,必须写0777
返回值:成功返回代表该文件的文件描述符,失败返回-1
/
/

通常情况下,程序在运行当中出现的任何错误,不应该显示在终端上,因为在大型项目当中,1:无法实时检测终端,2:即使实时检测终端,也不可能一只在一个页面保持很久,会被新出现的内容刷新。所以,我们经常会看到,在很多程序的目录底下,会有一个错误日志一样的文本文件。这个文本文件其实就是保存了标准错误流中所有的信息。
错误日志的做法:2种做法
1:获取到标准错误流的信息(strerrno(errno)获取错误流的字符串),然后通过标准文件IO输出到指定文件中
这种方法会产生额外的系统开销
2:直接使用perror,将perror的输出直接输出到文件中
我们把这样的一个操作,叫做重定向
重定向:将一个文件的输出流/输入流/错误流 重新设定流向
终端上的重定向:shell + ‘>’ “指定的路径”,默认会将shell指令的标准输出流重定向到“指定的路径”
还有以下几种情况
shell + 1>1.c 将shell指令的标准输出流重定向到1.c
shell + 2>1.c 将shell指令的标准错误流重定向到1.c
shell + 1>1.c 2>&1 将shell指令的标准输出流重定向到1.c,并将shell指令的标准错误流重定向到标准输出流,由于标准输出流已经流向1.c,所以标准错误流此时也是流向1.c
以上都是终端上的重定向方式,那么代码中应该如何进行重定向
首先需要注意的是:终端上的重定向方式都是临时的,代码中的重定向,在终端关闭之前,都是有效的,所以一定记得当无需重定向的时候,必须将之前重定向到其他地方的标准流重定向回来
使用函数 dup和dup2来解决重定向问题
函数名: dup
头文件: unistd.h
函数参数: int oldfd
函数返回值:int newfd / -1
分析: 将 oldfd 复制一份拷贝并命名为 newfd,如果失败,返回-1

	函数名: dup2
	函数参数:int newfd,int oldfd
	函数返回值:int newfd / -1
	分析: 将oldfd重定向到newfd,并返回newfd,如果失败返回-1	

/
/

当使用read读取文件的时候,我们可以选择性的读取一部分的内容
到目前为止,read或者fread函数,只能从文件的开头开始读取数据,但是,需求是从文件的指定位置开始读取数据
使用函数lseek实现功能
函数名:lseek
函数参数:int fd,int size,int mode
fd:带操作的文件描述符
size:从mode位置偏移size个字节开始读取文件
mode:
SEEK_SET:从文件的开头位置开始偏移
SEEK_CUR:从文件的当前位置开始偏移
SEEK_END:从文件的末尾位置开始偏移
/
/

如何更改已经打开的文件的属性:使用函数fcntl
函数名:fcntl
头文件:fcntl.h , unistd.h
函数参数:int fd , int cmd , …(arg)
fd : 等待操作的文件描述符
cmd : 操作文件的方式,常用的有两种方式
F_GETFL:这个操作就会获取到fd所代表的文件的所有属性,并返回。也就是说,如果第二个参数传的是F_GETFL,那么就会返回fd这个文件描述符的mode
F_SETFL:这个操作就会去重新设定fd的mode,以arg来设定fd的mode,所以,如果第二个参数传入的是F_SETFL,那么此时,就必须传入第三个参数,第三个参数就是新的mode
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值