Linux-UNIX系统编程手册第五章笔记

fcntl()

int fuctl(int fd ,int cmd ,…);

作用 fcntl()的用途之一是针对一个打开的文件,获取或修改其访问模式和状态标志(这些值是
通过指定open()函数获取的,

->获取设置 , cmd参数设置为F_GETFL 。


int flags ,accessMode ;
flags = fcntl(fd,F_GETFL);
//在上述代码之后,可以以如下代码测试文件是否以同步写方式打开:
if(flags & O_SYNC){
    printf("writes are ");
}
//判断文件访问模式

accessMode =flags & O_ACCMODE;//先与掩码O_ACCMODE做与运算
if(accessMode ==O_WRONLY || accessMode == O_RDWR){
    printf("file is writable\n");
}

掩码:掩码”通常指的是用于隐藏、保护或限制信息的一种方法

在C语言中,O_ACCMODE 是一个常量,用于确定文件打开模式的访问模式掩码。
它通常与 open() 系统调用一起使用,用于打开文件并指定访问模式。

在C语言中,O_ACCMODE 是一个常量,用于确定文件打开模式的访问模式掩码。它通常与 open() 系统调用一起使用,用于打开文件并指定访问模式。

在 POSIX 标准中,O_ACCMODE 是一个位掩码,用于提取 open() 函数中访问模式的部分。它定义了文件描述符的访问模式。具体来说,它包含以下值:

O_RDONLY:只读模式(read-only)。
O_WRONLY:只写模式(write-only)。
O_RDWR:读写模式(read-write)。

->修改打开文件的状态

可以使用 fcntl()的 F_GETFL 命令来获取当前标志的副本,
然后修改需要变更的比特位,最后再次调用 fcntl()函数的 F_SETFL 命令来更新此状态标志。
因此,为了添加 O_APPEND 标志,可以编写如下代码:

int flags;

flags=fcntl(fd,F_GETFL);
if(flags==-1) errExit("fcntl");

flags |=O_APPEND;//为flags添加追加模式(改变文件偏移量)  位操作
if(fcntl(fd,F_SETFL,flags)==-1)//f使用 fcntl() 函数以 F_SETFL 参数将更新后的 flags 重新设置到文件描述符 fd 中。
{
    errExit("fcntl");
}

文件描述符和打开文件之间的关系

文件描述符与打开文件非一一对应的关系,多个文件描述符可以指向同一个文件。

要理解具体情况如何,需要查看由内核维护的 3 个数据结构。

1进程级的文件描述符表。
2系统级的打开文件表。
3文件系统的 i-node 表。

表1->针对每一个进程 :内核为其维护 打开文件描述符(open file descriptor)表。
该表记录信息:
1 控制文件描述符操作的一组标志。(只有一个close-on-exec)(不太清楚这个是干嘛的 27章讲)
2 对打开文件句柄的引用(文件句柄值文件指针)

表2->系统级打开文件表;
记录信息:
1 文件偏移量:
2 打开文件时所使用的状态标志(flags)上部分说道过
3 文件访问模式(如调用 open()时所设置的只读模式、只写模式或读写模式)。
4 与信号驱动 I/O 相关的设置(见 63.3 节)。
5 对该文件 i-node 对象的引用。

后面2个其实不太理解

表3->系统级 i-node表
记录信息:
1 文件类型和访问权限
2 一个指针->指向文件所持有的锁的列表
3 文件的各种属性

文件锁是一种机制,用于控制对文件的访问,防止多个进程或线程同时对文件进行读取或写入操作而发生冲突。

复制文件描述符

dup();

int dup(int oldfd);

作用:调用复制一个打开的文件描述符 oldfd,并返回一个新描述符,二者都指向同一打开的文件句柄。
(系统会保证新描述符一定是编号值最低的未用文件描述符。)
头文件 :#include<unistd.h>

dup2();

int dup2(int oldfd ,int newfd);

作用:为 oldfd 参数所指定的文件描述符创建副本,其编号由 newfd 参数指定。
如果oldfd非有效的文件描述符 ,将会调用失败并放回错误EBADF,

dup3();

int dup3(int oldfd ,int newfd ,int flags);

增加一个掩码

在文件特定偏移量处的 I/O:pread()和 pwrite()

这两个函数 完成read()和write()相似的工作 ,

前者offser参数所指定的位置进行文件I/O操作,(而非始于文件的当前偏移量处 ,且它们不改变文件偏移量)
->多了offset参数

//函数定义
#include<unistd.h>

ssize_t pread(int fd, void *buf ,size_t count ,off_t offset);
// fd 文件描述符 ,buf 接收字符串  ,count 接收字数 ,offset文件偏移量
ssize_t pwrite(int fd ,const void *buf,size_t count ,off_t offset);
//

分散输入和集中输出(Scatter-Gather I/O):readv()和 writev()

#include<sys/uio.h>
struct iovec{
    void *iov_base;//buffer地址
    size_t iov_len;//字节长度
}
//头文件已经帮你定义好了

ssize_t readv(int fd ,const struct iovec *iov, int invcnt);
//返回 读取的字节数 ,0->EOF,(文件结束),-1->失败;

ssize_t writev(int fd ,const struct iovec *iov, int iovcnt);
//返回 写入的字节数 文件结束),-1->失败;

分散输入

原子性是 readv()的重要属性。换言之,从调用进程的角度来看,当调用 readv()时,内核
在 fd 所指代的文件与用户内存之间一次性地完成了数据转移。这意味着,假设即使有另一进
程(或线程)与其共享同一文件偏移量,且在调用 readv()的同时企图修改文件偏移量,readv()
所读取的数据仍将是连续的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值