Unix文件I/O

<Uinx 环境高级编程笔记>
1 常用的I/O
打开文件
int open( const char * pathname, int flags); 
int open( const char * pathname,int flags, mode_t mode);
返回值:文件描述符,一个整数。
头文件:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>
第一个参数: 欲打开的文件路径
flags: 访问模式,O_RDONLY, O_WRONLY, O_RDWR, O_CREAT,O_EXCL(判断文件是否存在), O_TRUNC,  O_NONBLOCK(非阻塞方式打开), O_APPEND.
mode:只有在建立新文件是才会生效。指定新建文件的属性。
open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode) 等价与 create(pathname, mode)
create的不足是只能也只写文件方式创建文件。即如果要创建一个临时文件可读可写,需要create, close然后再open。
 
关闭文件
关闭文件很简单, close函数,传给它要关闭的文件描述符就可以了。
当一个进程终止时,它所有打开的文件都由内核自动关闭。
 
文件定位
我们可以从文件的任何位置开始读写,这需要一个移动到指定位置的函数,就是lseek。
off_t lseek(int fildes,off_t offset ,int whence)
头文件:<sys/types.h> <unistd.h>
whence: 移动的参照位置,SEEK_SET(从文件开始), SEEK_CUR(从当前位置), SEEK_END(从文件尾)
offset: 偏移量
返回值: 文件的当前位移量
例子:假设文件内容为Hello, 那么文件长度为5
curpos = lseek(fd, 0, SEEK_SET);  //curpos为0
curpos = lseek(fd, 0, SEEK_CUR);  //curpos为0
curpos = lseek(fd, 0, SEEK_END);  //curpos为5
curpos = lseek(fd, 5, SEEK_END);  //curpos为10
curpos = lseek(fd, -11, SEEK_END);  //curpos为-1(error)
文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,
并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被读为0。
 
od -c file: 以字符方式打印文件内容。
 
读文件
ssize_t read(int fd,void * buf ,size_t count);
头文件:<unistd.h>
返回实际读到的字节数。
从终端设备读时,通常一次最多读一行。
 
写文件
ssize_t write (int fd,const void * buf,size_t count);
 
copy的一个简单实现
View Code
#define BUFFSIZE 8192
int main(int argc, char **argv)
{
    if (argc != 3)
    {
        printf("Usage: %s file1 file2\n", argv[0]);
        exit(1);
    }
    
    int fd1, fd2;
    fd1 = open(argv[1], O_RDONLY);
    fd2 = open(argv[2], O_WRONLY|O_CREAT | O_TRUNC, FILE_MODE);
    char s[BUFFSIZE];
    int n;
    printf("%d  %d\n", fd1, fd2);
    while ( (n=read(fd1, s, BUFFSIZE)) > 0)
    {
        printf("%s\n", s);
        write(fd2, s, n);
        perror("write");
    }
    
    close(fd1);
    close(fd2);
}

 

2 I/O的效率
不同的I/O长度对读写时间有影响。
在上面的程序中,BUFFSIZE 会影响复制的效率。系统CPU时间的最小值开始出现在BUFFSIZE为8192处,继续增加缓存长度对此时间并无影响。--《Unix环境高级编程》
 
3 文件共享
每个打开的进程也下面三个结构相关
1 文件描符表 -- 包括文件描述符标志、指向一个文件表项的指针。
2 每一个打开的文件都有一张文件表 -- 包括文件状态标志、当前文件位移量、指向文件v节点的指针。
3 每个打开的文件都有一个v节点结构。-- v节点包含了文件类型和对此文件进行各种操作的函数的指针信息。
v节点还包含了该文件的i节点。i节点包含了文件的所有者、文件长度、文件所在的设备。
v节点一般是共享的。文件表项一般是独立的 -- 这种安排使每个进程都有它自己的对该文件的位移量。
 
int newfd= dup(oldfd)
dup之后使用同一份文件表。newfd和oldfd指的是同一个文件,共享所有的锁定、读写位置,权限或旗标。
 
fcntl
可以用来改变已打开文件的性质。也可用来获得打开文件的各种属性。
int fcntl(int fd , int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock * lock);
 
val = fcntl(fd, F_GETFL, 0); 
accmode = val & O_ACCMODE;
if (accmode == O_RDONLY) printf("read only");
else if (accmode == O_WRONLY) printf("write only");
else if (accmode == O_RDWR) printf("read write");
 
a.out 0</dev/tty
表示在文件描述符0上打开读
a.out 1>temp.foo
表示在文件描述符1上打开写,写到标准输出的都会转移到文件temp.foo
a.out 2 2>>temp.foo
表示在文件描述符2上打开写,添加到文件尾。
a.out 5 5 <>temp.foo
表示在文件描述符5上打开temp.foo以供读写。
 
 
read, write都因系统调用而进入内核,所以称这些函数为不带缓存的I/O函数。
如启用添加标志打开文件,便只能在末尾写。但可以在任意位置读。有写操作时,会自动定位到文件尾进行写操作。
发布了139 篇原创文章 · 获赞 45 · 访问量 17万+

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览