Linux系统编程五(第5章)

1.所有的系统调用都是原子的。
2.open系统调用时同时指定O_EXCL与O_CREAT标志,就可以确保进程是打开文件的创建者。因为如果指定O_EXCL,如果文件存在,则会返回错误。这两个标志同时指定,就可以确保在原子操作內检测文件是否存在并创建和打开文件。
还可以利用O_APPEND标志来保证每次都在文件的末尾添加内容。还不是用lseek先seek到文件末尾,然后写入,这样不能保证原子操作。
3.fcntl()
fcntl.h
int fcntl(int fd, int cmd, …);
第三个参数以省略号表示,意味着可以将其设置为不同的类型,或者加以省略。内核会依据cmd参数(如果有的话)的值来确定该参数的数据类型。
a.用途之一是针对一个打开的文件,获取或者修改其访问模式和状态标志(这些值是通过指定open调用的flag参数来设置的)。要获取这些设置,cmd为F_GETFL。设置为F_SETFL。

4.文件描述符和打开文件之间的关系:
Linux系统维护了三个表,进程级的文件描述符表,系统级的打开文件表,文件系统的i-node表。
进程级的文件描述符表记录本进程所有打开的文件描述符。文件描述符只有close-on-exec属性。
系统级的打开文件表是文件句柄的引用,文件句柄保存了所有与打开文件有关的全部信息。包括文件偏移量,打开标志,访问模式等等。每调用一次open,产生一个文件句柄。
文件系统的i-node表记录的是文件的属性(比如文件锁)。
一个进程中可以允许多个文件描述符(fd)指向同一个文件句柄,这种现象一般是由dup(), dup2(),fcntl对文件描述符的复制造成的,这种情况下多个fd共享同一个文件偏移量等文件句柄拥有的属性。。注意不是对同一个文件调用两次open造成的。两次对同一个文件调用open会生成两个句柄。同时,就算指向同一个文件句柄的不同描述符分别属于不同的进程(通过unix domain传输的fd),也共享文件句柄的属性。
unistd.h
int dup(int oldfd);复制oldfd,产生一个新的fd,指向同一个文件句柄。
int dup2(int oldfd, int newfd);复制oldfd,利用newfd来作为新的描述符,如果newfd已经被占用了,该函数会首先将其关闭。
fcntlde F_DUPFD操作是复制文件描述符的另一个借口,更具灵活性
newfd = fcntl(oldfd, F_DUPFD,startfd);创建oldfd的副本,并且利用大于等于startfd的最小未用的值作为newfd。
5.分散输入和集中输出(原子操作的优点)
sys/uio.h
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, struct iovec *iov, int iovcnt);
struct iovec {
void *iov_base; //start address of buffer
ssize_t iov_len; // Number of bytes to transfer to/from buffer.
}
readv()系统调用实现了分散输入的功能,从fd中读取一片连续的数据,然后将其散置于iov指定的缓冲区內。从iov[0]开始,依次填满每个缓冲区。
writev()将iov指定的所有缓冲区的数据拼接起来,将连续的字节写入fd所指带的文件中。
这两个系统调用的好处就是可以原子的将不同的buf同时写入文件或者从文件中连续的数据分别写入不同的地址。
6.在特定文件偏移量处IO
unistd.h
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
原子的将数据从某个位置写入或者读出,不改变fd的偏移量。
7.还可以将5,6联合起来的系统调用。BSD支持
preadv(), pwritev().
define _BSD_SOURCE
include sys/uio.h
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, struct iovec *iov, int iovcnt, off_t offset)
8.截断文件
unistd.h
int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);
若文件当前长度大于参数length,调用将丢弃超出部分,若小于length,将在文件尾部添加空字节或者一个文件空洞。
两个调用之间的差别在于一个是以路径名为参数,不需要提前打开。另一个需要提前open,然后传入fd。
9.大文件IO
在32位架构中,off_t为一个int32_t,最多可以表示2G大小的文件。为了能访问大于2G的文件,需要启用LFS功能。
cc -D_FILE_OFFSET_BITS=64
或者在c语言的源文件中,包含 define _FILE_OFFSET_BITS 64
10.创建临时文件:
stdlib.h
int mkstemp(char *template);
传入路径名,函数会返回一个可读写的fd。示例如下:
int fd;
char template[] = “/tmp/somestringXXXXXX”;//最后6个字符必须为XXXXXX
fd = mkstemp(template);
if (fd < 0) {
error
}
unlink(template);
close(fd);

stdio.h
FILE *tmpfile(void);
返回一个文件流,文件流关闭后文件自动删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值