linux系统编程之文件I/O

来源:互联网 发布:淘宝护盾图片怎么授权 编辑:程序博客网 时间:2024/05/16 04:33

一、文件描述符      

       linux系统中,所有打开的文件都对应一个数字,这个数字由系统来分配,称为文件描述符。

       PCB进程控制块里有文件描述符表,以数组形式存放于内核区。

        一个进程默认打开3个文件描述符  STDIN_FILENO 0   STDOUT_FILENO 1  STDERR_FILENO 2

        新打开文件返回文件描述符表中未使用的最小文件描述符。

二、open函数

        可以打开或创建一个文件。

        头文件
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <fcntl.h>

        函数原型
        int open(const char *pathname, int flags);
        int open(const char *pathname, int flags, mode_t mode);
        返回值:成功返回新分配的文件描述符,出错返回-1并设置errno

三、read/write 函数

头文件

#include <unistd.h>

函数原型

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
 


四、阻塞与非阻塞

读常规文件是不会阻塞的不管读多少字节,read一定会在有限的时间内返回。从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻
塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。同样,写常规文件是不会阻塞的,而
向终端设备或网络写则不一定。

阻塞(Block) 当进程调用一个阻塞的系统函数时,该进程被置于睡眠(Sleep)状态,这时内核调度其它进程运行,直到该进程等待的事件发生了(比如网络上接收到数据包,或者调用sleep指定的睡眠时间到了)它才有可能继续运行。与睡
眠状态相对的是运行(Running)状态,在Linux内核中,处于运行状态的进程分为两种情况:
1正在被调度执行;(2)就绪状态。

非阻塞I/O有一个缺点,如果所有设备都一直没有数据到达,调用者需要反复查询做无用功,如果阻塞在那里,操作系统可以调度别的进程执行,就不会做无用功了。

用非阻塞I/O实现等待超时,既保证了超时退出的逻辑又保证了有数据到达时处理延迟较小 。现给出代码:

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define MSG_TRY "try again\n"
#define MSG_TIMEOUT "timeout\n"
int main(void)
{
char buf[10];
int fd, n, i;
fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
if(fd<0) {
perror("open /dev/tty");
exit(1);
}
for(i=0; i<5; i++) {
n = read(fd, buf, 10);
if(n>=0)
break;
if(errno!=EAGAIN) {
perror("read /dev/tty");
exit(1);
}
sleep(1);
write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
}
if(i==5)
write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT));
else
write(STDOUT_FILENO, buf, n);
close(fd);
return 0;
}


五、lseek函数

每个打开的文件都记录着当前读写位置,打开文件时读写位置是0,表示文件开头,通常读写多少个字节就会将读写位置往后移多少个字节。但是有一个例外,如果以O_APPEND方
式打开,每次写操作都会在文件末尾追加数据,然后将读写位置移到新的文件末尾。

头文件   

#include <sys/types.h>
   #include <unistd.h> 

函数原型

off_t lseek(int fd, off_t offset, int whence);
若lseek成功执行,则返回新的偏移量。
六、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);

阅读全文
0 0
原创粉丝点击