学习笔记之文件与I/O

本文是学习linux C一站式学习的笔记

在unix中,所有的I/O设备,如网络磁盘和终端都被模型化为文件,而所以输人和输出都被当成对相应文件的读和写来执行,大多数unix文件I/O只需用到5个函数:open,read,write,lseek以及close。相对于ANSI C而言,这些函数被称为不带缓存的I/O,不带缓存指每个read和write都调用内核中的一个系统调用。

一、I/O函数介绍

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);//返回值:成功返回新分配的文件描述符,出错返回-1并设置errno
ssize_t read(int fd, void *buf, size_t count);//返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
ssize_t write(int fd, const void *buf, size_t count);//返回值:成功返回写入的字节数,出错返回-1并设置errno
off_t lseek(int fd, off_t offset, int whence);
int close(int fd);//返回值:成功返回0,出错返回-1并设置errno
1)open函数可以打开或创建一个文件

参数介绍:pathname:要打开或创建的文件名,和fopen一样,pathname既可以是相对路径也可以是绝对路径;
    flag:有一系列常数值可供选择,可以同时选择多个常数用按位或运算符连接起来;

必选项:以下三个常数中必须指定一个,且仅允许指定一个。

O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 可读可写打开

以下可选项可以同时指定0个或多个,和必选项按位或起来作为flags参数。可选项有很多。

O_APPEND 表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容。
O_CREAT 若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该文件的访问权限。

             O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断(Truncate)为0字节。

             O_NONBLOCK 对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O(Nonblock I/O)

               mode:指明文件权限,每个进程都有一个umask,它是通过调用umask函数来设置的,当进程通过带某个mode参数的open函数来创建一个新文件时,文件的访问权限被设置为mode&~umask,可以用八进制数表示,比如0644表示-rw-r--r--

2)read和write函数

read函数参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。write的返回值通常等于请求写的字节数count,而向终端设备或网络写则不一定。

3)lseek参数offset和whence的含义和fseek函数完全相同。只不过第一个参数换成了文件描述符。和fseek一样,偏移量允许超过文件末尾,这种情况下对该文件的下一次写操作将延长文件,中间空洞的部分读出来都是0。lseek成功时返回当前偏移量失败时返回-1。

二,fcntl函数

可以用fcntl函数改变一个已打开的文件的属性,可以重新设置读、写、追加、非阻塞等标志(这些标志称为File Status Flag),而不必重新open文件。

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
fcntl函数有五种功能:
• 复制一个现存的描述符(c m d=F _ D U P F D) 。
• 获得/设置文件描述符标记(c m d = F _ G E T F D或F _ S E T F D) 。
• 获得/设置文件状态标志(c m d = F _ G E T F L或F _ S E T F L) 。
• 获得/设置异步I / O有权(c m d = F _ G E TO W N或F _ S E TO W N) 。
• 获得/设置记录锁(c m d = F _ G E T L K , F _ S E T L K或F _ S E T L K W) 。
实例:

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
	char buf[10];
	int n;
	int flags;
	flags = fcntl(STDIN_FILENO, F_GETFL);//获取文件状态标识
	flags |= O_NONBLOCK;//改变标识
	if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1) {//设置标识
		perror("fcntl");
		exit(1);
	}
        ....
	return 0;
}
三、ioctl

可以通过fcntl设置的都是当前进程如何访问设备或文件的访问控制属性,例如读、写、追加、非阻塞、加锁等,但并不设置文件或设备本身的属性,例如文件的读写权限、串口波特率等。ioctl用于向设备发控制和配置命令,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的。

#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
d是某个设备的文件描述符。request是ioctl的命令,可变参数取决于request,通常是一个指向变量或结构体的指针。若出错则返回-1,若成功则返回其他值,返回值也是取决于request。

四、unix  基本I/O模型

1,阻塞I/O:最流行的I/O模型是阻塞I/O(blocking I/O)模型。缺省情况下,所有套接口都是阻塞的。

2,非阻塞I/O:进程把一个套接口设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。

3,I/O复用(select和poll):我们就可以调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上。

4,信号驱动I/O(SIGIO):我们也可以用信号,让内核在描述字就绪时发送SIGIO信号通知我们

5,异步I/O(POSIX的aio_系列函数):异步I/O(asynchronous I/O)由POSIX规范定义。一般的说,这些函数的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到我们自己的缓冲区)完成后通知我们。这种模型和信号驱动模型的主要区别在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。


部分内容摘自:http://his9932.blog.51cto.com/2915040/632667

参考资料:http://blog.sina.com.cn/s/blog_5f4344bf0100cklt.html

                     http://www.2beanet.com/linux/ch28.html



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值