AUP学习笔记--基本的I/O系统调用

来源:互联网 发布:surface rt安装linux 编辑:程序博客网 时间:2024/06/13 03:05

  最近在读高级unix编程一书,没事就写写总结吧,把一些重点内容记录下来,以后要复习或者找资料的话还可以省点时间,闲话不多说,unix下系统编程我想跟Linux下的应该没什么区别,一般说来我会直接在linux下进行实验,说到这里,前些天把自己的本整成了双系统,分了六十G给fedora16,使用GNOME3感觉很清爽,界面也很炫,一些工作上用到的toolchain也配置好了,还以为有多么复杂,没想到只需要改个路径就可以~!这章的内容应该是在十天前看的,主要内容也就是几个系统调用函数的使用,包括open/creat/close/read/write/lseek/umask/unlink,这些应该是用的比较多的了,其他的比如pread/pwrite/readv/writev这几个好像见得不多,没有太细看,大概知道是干嘛的,下面具体说说这几个函数的用法:

1.open

#include <sys/stat.h>#include <fcntl.h>/* Return fd or -1 on error,set errno */int open(const char *path, /* file path name */  int flags, /* open flags */mode_t perms /* permissions(when creating) */);
可以用open来打开一个已经存在的文件(普通文件、特殊文件或命名管道)或者创建一个新的文件,但只能创建普通文件。文件一旦打开的话,open以及相关的read、write、lseek、close调用就可以使用返回的文件描述符。

flags的取值:

O_RDONLY  以只读方式打开文件,O_WRONLY 以只写方式打开文件,O_RDWR 以可读写方式打开文件

对于一个已经存在的文件,参数perms是没有用的,通常省略,文件偏移量(读写用到的)位于文件的第一个字节,比如打开一个存在的文件:

int fd;fd = open("/home/rudyn/tmpfile", O_RDONLY);

用open创建一个新的文件,需要在flags中加入标志O_CREATE,当然还要结合O_WRONLY或者O_RDWR一起用,不然的话创建的文件就是个只读的,意义不大,这个时候perms参数就要用得上了:

fd = open("/home/rudyn/tmpfile", O_RDWR | O_CREATE, PERM_FILE);
如果需要创建一个新的、没有任何内容的文件,或者说该文件存在,但是要将其数据清涂并置文件偏移量为0,那么flag:O_TRUNC可以实现这种功能。因此可以在上句中加入这个标志,不过O_TRUNC会破坏文件的数据,因此只要相应的进程具有写的权限,那么它就可以清除文件的内容,也就是对O_RDONLY的文件不起任何作用。

2.creat

#include <sys/stat.h>#include <fcntl.h>int creat(const char *file_path, /* path name */mode_t perms /* permissions */);/* return fd or -l on error */
实际上,creat只是一个宏定义:
#define creat(path, perms) open(path, O_WRONLY|O_CREAT|O_TRUNC, perms)
标志:O_EXCL,如果它和O_CREAT标记一起使用,文件若存在,则创建文件操作失败,如果没有用O_CREAT,open的操作是文件存在则打开,文件不存在则失败,而和O_EXCL|O_CREAT这个标志用的时候,open的结果将会是:文件不存在,则创建否则失败。

这章中还讲到了用文件当锁的内容,通过O_EXCL这个标志来实现,判断文件的存在性来控制进程的状态,虽然书中也说效率低,但是也是一种思想!

3.unlink

#include <unistd.h>/* Return 0 on success or -1 on error */int unlink(  const char *path; /* path name */);
unlink能从目录中删除链接,并将信息节点所引用的文件链接数减一,如果链接数减到零,文件系统将删除这个文件它所占用的磁盘空间可再次被利用,信息节点也可被重用。它可以解除任何类型的文件,但是只有超级用户才可以解链目录,不过解链目录还是应该用rmdir()。
4.umask

#include <sys/stat.h>mode_t umask(mode_t mask; /* new mask value */);/* Return previous mask  */
linux中新创建的文件都有个默认的文件权限,它由九个位决定,比如某文件:-rwx-r-x-r-x,用数字表示为755,那么系统的默认umask值(对于文件来说)就是:022,umask是为了设置和得到文件模式的创建掩码,umask不会返回error,它总返回之前的值。

5.mkstemp和tmpfile

这两件函数是标准C中的内容,不再说了,回头翻下C标准库就行,它们用于创建一个临时的文件。

6.文件偏移量以及标志O_APPEND

文件打开的时候,如果没有偏移标志指定,其偏移量为零,读或写都会自动改变偏移量,文件偏移量是下一次读或写文件的位置,但是目录、套接字、命名管道和符号链接文件都没有文件偏移量。当文件以O_APPEND标志打开时,进行的读写操作都将通过隐含的lseek将文件偏移量设置在文件末尾,而不会覆盖前面的内容。
7.lseek

#include <unistd.h>off_t lseek(int fd,           /* file descriptor */off_t pos,     /* position */int whence   /* interpretation */);/* Return new fd or -1 on error */
参数whence取值:

SEEK_SET      将该文件偏移量设置到pos参数

SEEK_CUR    将该文件偏移量设置为其当前值加pos参数,pos可为正数,负数或0,0是查找当前文件偏移量

SEEK_END    将该文件偏移量设置为文件长度加pos参数,pos可为正数,负数或0,0是将文件偏移量设置为文件结尾

lseek最常用的三种方式:

(1).查找文件某个绝对位置

lseek(fd, offset, SEEK_SET);
(2).查找文件末尾

lseek(fd, 0, SEEK_END);
(3).查找文件偏移量当前位置

off_t cur_pos;cur_pos = lseek(fd, 0, SEEK_CUR);
8.read

#include <unistd.h>ssize_t read(int fd,        /* file descriptor */void *buf,  /* buf for receiving data */size_t nbytes  /* total to read */);
read从fd描述的打开文件中读取nbytes数据至buf中。从当前文件偏移量开始读,完成读操作后,文件偏移量将增加所读字节数。返回值是所读字节数、文件结束标志0或者错误标志-1,读不受O_APPEND影响。如果需要读所有的数据,最好通过循环调用read,后面有个copy file的例子说明这一点。

9.write

#include <unistd.h>ssize_t write(int fd,    /* file descriptor */const void *buf,  /* data to write */size_t nbytes     /* total to write */);/* Return number of bytes written or -1 on error */
write将buf指缓冲区的nbytes字节写入fd所打开的文件中,写操作从文件偏移量当前位置开始,完成之后移动文件偏移量,若写入成功,返回已写的字节数,出错为-1。

10.close

#include <unistd.h>int close(    int fd     /* file descriptor */);/* return 0 on success or -1 on error */
close没有做任何工作,仅仅使文件描述符可重用,删除打开的文件描述。

最后,附上两个文件读写的小程序,可以比较,帮助更好的理解系统调用:

File Copy A:

#define BUFSIZE 512void file_copy_a(char *src, char *dst){    int src_fd = -1, dst_fd = -1;    ssize_t byte_read;    char buf[BUFSIZE] = {0};    if (-1 == (src_fd = open(src, O_RDONLY)))    {        perror("File open error!\n");        goto end;    }    if (-1 == (dst_fd= open(dst, O_WRONLY | O_CREAT | O_TRUNC)))    {        perror("File create error!\n");        goto end;    }    while ((byte_read = read(src_fd, buf, sizeof(buf))) > 0)    {        if (write(dst_fd, buf, byte_read) != byte_read)        {            perror("write error!\n");            goto end;        }    }    if (byte_read == -1)    {        perror("read error!\n");        goto end;    }    end:    if(src_fd > 0)    {        close(src_fd);    }        if(dst_fd > 0)    {        close(dst_fd);    }}

File Copy B:

#define BUFSIZE 512void file_copy_B(char *src, char *dst){    int src_fd = -1, dst_fd = -1;    ssize_t byte_read, byte_write, n;    char buf[BUFSIZE] = {0};    if (-1 == (src_fd = open(src, O_RDONLY)))    {        perror("File open error!\n");        goto end;    }    if (-1 == (dst_fd= open(dst, O_WRONLY | O_CREAT | O_TRUNC)))    {        perror("File create error!\n");        goto end;    }    while ((byte_read = read(src_fd, buf, sizeof(buf))) > 0)    {        byte_write = 0;        do        {            if((n = write(dst_fd, &buf[byte_write], byte_read - byte_write)) < 0)            {                perror("write error!\n");                goto end;            }            byte_write += n;                    }while(byte_write < byte_read);    }    if (byte_read == -1)    {        perror("read error!\n");        goto end;    }    end:    if(src_fd > 0)    {        close(src_fd);    }        if(dst_fd > 0)    {        close(dst_fd);    }}















原创粉丝点击