APUE 第三章

 又一次看完APUE第三章,有了新的收获,总结一下第三章。

第三章讲的是POSIX的文件I/O,不带缓冲的I/O,相对于与第五章ISO C的标准I/O。


不带缓冲的I/O 与带缓冲的I/O


书上对于不带I/O的解释是每个I/O操作调用内核中一个系统调用。当然这个答案完全不能让读者弄明白到底是什么意思。

   取自一网友的理解:

所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲,当用write函数对其写数据时,直接调用系统调用,将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才会把数据写入磁盘。因此所谓的不带缓冲的I/O是指进程不提供缓冲功能。每调用一次write或read函数,直接系统调用。
而带缓冲的I/O是指进程对输入输出流进行了改进,提供了一个流缓冲,当用fwrite函数网磁盘写数据时,先把数据写入流缓冲区中,当达到一定条件,比如流缓冲区满了,或刷新流缓冲,这时候才会把数据一次送往内核提供的块缓冲,再经块缓冲写入磁盘。
因此,带缓冲的I/O在往磁盘写入相同的数据量时,会比不带缓冲的I/O调用系统调用的次数要少。


文件描述符

   对于内核而言,所有的打开文件都通过文件描述符引用 (FileDescriptor),是一个非负整数,对于打开的文件内核会返回一个文件描述符,我们可以通过文件描述对打开的文件进行读写操作。

   通常而言文件描述符 0,1,3 分别代表了  标准输入、标准输出、标准错误输出,关于对应的符号常亮被定义在<unistd.h>中。


    每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表

   (a)  文件描述符标志。
(b)  指向一个文件表项的指针。

     内核为所有打开文件维持一张文件表。每个文件表项包含:
     (a)  文件状态标志(读、写、增写、同步、非阻塞等 )。
     (b)  当前文件位移量

     (c)  指向该文件v节点表项的指针

     



假设在一个系统中存在很多进程(process),每个进程里面有一个文件 描述符表,大致结构如下:

struct Process{
    //这是一个数组,文件描述符就是下标。
    vector<FileDescriptorEntry> entries;
};
struct FileDescriptorEntry{
    bool close_on_exec; //调用exec是否关闭
    bool other_flags; //其他标记
    OpenedFileTable* ft_ptr; //指向全局的打开文件表表项
};

然后系统维护一个打开表文件表表项,在每个进程的文件描述符里面有对应的表项指针。大致结构如下:

struct OpenedFileTable{
    int status; //状态标志,比如O_RDWR,O_APPEND,OSYNC等。
    off_t offset; //当前偏移
    vnode_t* vnode; //所指向的vnode
};

在进程复制一个文件描述符并没有增加一个新的表项,而是指向相同的表项。然后vnode 就是文件系统对应的内容了,包括位置大小属性等等信息。




文件共享


关于文件共享的例子:看课后习题3.3。

1.如果两个独立的进程各自打开同一一个文件,我们会发先我们生成的两个文件描述符,打开盖文件的每个进程都得到了一个文件表项,但是对应的V节点表项却是同一个。这样的安排是得每个进程都有自己的对改文件有自己的偏移量。

               2、当我们使用dup函数复制文件描述符和这种情况的区别就是fd指向文件表是同一个,因此我们可以使用dup来复制一个现存的文件描述符。


关于close-on-exec :

每个文件描述符都有一个close-on-exec标志。默认情况下,这个标志最后一位被设置为 0。

这个标志符的具体作用在于当开辟其他进程调用exec()族函数时,在调用exec函数之前为exec族函数释放对应的文件描述符。


I/O操作:

int open(const char *pathname ,int oflage ..../*mode_t mode*/)

常用mode :O_RDONLY O_WRONLY O_RDWR O_APPEND O_CREAT

int close(int filedes);

off_t lseek(int filedes ,off_t offset ,int whence);

SEEK_SET SEEK_CUR SEEK_END

size_t read (int filedes, void * buf ,size_t nbytes);

size_t write(int filedes, void * buf ,size_t nbytes);


int ioctl(int filedes,int request,... );




   



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值