新闻  |   论坛  |   博客  |   在线研讨会
文件 I/O编程
mayer | 2009-05-22 18:44:09    阅读:1623   发布文章

文件 I/O编程

 

linux的API遵循了unix中最流行的界面标准—POSIX标准。

 

Linux文件主要分为4种:普通文件、目录文件、链接文件和设备文件。

 

通常,一个进程启动时,都会打开3个文件:标准输入(STDIN_FILENO)、标准输出(STDOUT_FILENO)和标准出错(STDERR_FILENO)处理。分别对应的文件描述符为0、1、2.

不带缓存的文件I/O操作

相关函数:open,close,read,write,lseek,fcntl,select

open 

打开或者创建文件

int open(const char *pathname,flags,int perms)

pathname:打开文件名

flags:打开方式

perms 打开权限

返回文件描述符

close

关闭一个已经打开的文件

int close(int fd)

fd:文件描述符

 

read

从文件描述符中读出文件的指定内容

ssize_t read(int fd,void *buf,size_t count)

fd  文件描述符

buf 存放读取数据的缓存

count 读取数据的字节数

返回 成功:读到的字节数

0:已经读到文件尾

-1:出错

 

write

向打开的文件写数据

ssize_t write(int fd,void *buf, size_t count)

fd  文件描述符

buf 存放要写的数据的缓存

count 写数据的字节数

返回 成功:已写的字节数

-1:出错

 

lseek

在指定文件中精确定位

off_t lseek(int fd,off_t offset,int whence)

offset: 偏移量

whence:当前位置的基点

 

fcntl

文件描述符控制函数

int fcntl(int fd,int cmd,struct flock *lock)

cmd: 命令类型

lock: struct flock

       {

              short  l_type;       //锁类型

        off_t  l_start;             //上锁开始位置(偏移量)

           short  l_whence;    //基点

              off_t  l_len;        //锁的长度

          pid_t  l_pid;       //

}

select

I/O多路复用监视函数

int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exeptfds,struct timeval *timeout)

struct timeval{

long   tv_sec;     /* seconds */
long   tv_usec;    /* microseconds */
};

numfds  需要检查的号码的最高的文件描述符加1

readfds  由select监视的读文件描述符集合

writefds  由select监视的写文件描述符集合

exeptfds 由select监视的异常文件描述符集合

timeout  等待时间

NULL 永久等待

0 测试完即返回 

timeval时间

返回 –1表示出错 0表示超时 若成功则返回准备好的文件描述符

FD_ZERO(fd_set *fdset):清空fdset与所有文件描述符的联系。

FD_SET(int fd, fd_set *fdset):建立文件描述符fd与fdset的联系。

FD_CLR(int fd, fd_set *fdset):清除文件描述符fd与fdset的联系。

FD_ISSET(int fd, fd_set *fdset):检查fd_set联系的文件描述符fd是否可读写,>0表示可读写。

 

Fopenfdopenfreopenfreadfwritegetcputc…

 

 

 

 

 

 

总结:

注意:open,close,read,write,lseek,fcntl,select以及带级存的fopen等函数的用法。特别注意fcntl及select的用法。Fcntl在本章作用为给文件加锁解锁。Select用来实现多路I/O的复用。

 

读取锁为共享型锁,可以建立多个

写入锁为互斥型锁,只能建立一个

写入锁跟读取锁不能同时建立

 

fcntl默认的为建议性锁,顾名思义,如果一个进程为文件建立了一个写入锁,那么另一个进程对此文件写操作时先人为判断一下有没有写入锁,如果没有,则可进行写操作。如果有,则不可进行写操作,需等待对方解锁。个人理解这更是一种双方协商的锁,完全靠自觉性,如果不判断写入锁是否存在而直接对文件写操作也可以写入数据。而强制性锁则为强制性的,一个进程加了强制性锁之后,另一个进程就不可以对文件做相应操作。

 

串口 阻塞型 非阻塞型

打开->设置->读写

 

fopen,open

1. fopen 系列是标准的C库函数;open系列是 POSIX 定义的,是UNIX系统里的system call。

也就是说,fopen系列更具有可移植性;而open系列只能用在 POSIX 的操作系统上。

 

2. 使用fopen 系列函数时要定义一个指代文件的对象,被称为“文件句柄”(file handler),是一个结构体;而open系列使用的是一个被称为“文件描述符” (file descriptor)的int型整数。

 

3. fopen 系列是级别较高的I/O,读写时使用缓冲;而open系列相对低层,更接近操作系统,读写时没有缓冲。由于能更多地与操作系统打交道,open系列可以访问更改一些fopen系列无法访问的信息,如查看文件的读写权限。这些额外的功能通常因系统而异。

 

4. 使用fopen系列函数需要"#include <sdtio.h>";使用open系列函数需要"#include <fcntl.h>" ,链接时要之用libc(-lc)

 

select函数 , I/O多路复用。可以对指定的字符集进行监视。select系统调用是用来让我们的程序监视多个文件句柄(file descriptor)的状态变化的。

例:如果我们要检测用户是否按了键盘进行输入,我们就应该把标准输入0这个句柄放到select里来检测,如下:
FD_ZERO(&rdfds);
FD_SET(0, &rdfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(1, &rdfds, NULL, NULL, &tv); /* 注意是最大值还要加1 */
if(ret < 0) perror("select");/* 出错 */
else if(ret == 0) printf("超时\n"); /* 在我们设定的时间tv内,用户没有按键盘 */
else { /* 用户有按键盘,要读取用户的输入 */
    scanf("%s", buf);

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客