最近在读高级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 512
void 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 512
void 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);
}
}