Linux 文件IO

本文介绍了如何使用open和creat函数创建文件,并设置文件权限。详细解释了read和write函数进行文件读写的方法,以及如何利用lseek调整文件读写位置。此外还探讨了通过stat和fstat获取文件属性,包括如何解析st_mode字段来确定文件类型。
open,create:


fcntl.h
sys/types.h
sys/stat.h


int open(const char* pathname, int flags, [mode_t mode]);
flags:O_RDONLY  O_WRONLY  O_RDWR
      O_CREAT O_EXCL O_TRUNC  O_APPEND //根据[mode_t mode]中给出的权限使用


int creat(const char *pathname, mode_t mode); //mode为赋予文件的访问权限




write,read:


unistd.h


ssize_t write(int fd, const void *buffer, size_t n);//把buffer写入fd,返回实际写入的字节数


ssize_t read(int fd, void *buffer, size_t nbytes); //nbytes是从fd中读取的字节数,把fd写入buffer,返回世界写入的字节数






stat:


sys/stat.h


int stat(const char *pathname, struct stat *infobuf);
int stat(const char *path,  struct stat *infobuf);
int fstat(int fd,  struct stat *infobuf);
功能:获取文件属性
stat:通过文件路径获取
fstat:通过文件描述符获取
lstat:通过文件路径获取,若查询符号链接文件,仅查其本身属性而不是所链接文件属性。
参数:
infobuf:返回的文件属性(结构体)
返回值:成功返回0,否则返回-1


st_mode:
解释st_mode标志的掩码包括:
S_IFMT          文件类型
S_IRWXU      所属者的读/写/执行权限
S_IRWXG      所属组的读/写/执行权限
S_IRWXO      其他用户的读/写/执行权限


#define    S_IFBLK     0060000   文件是一个特殊块设备
#define    S_IFDIR      0040000   文件是一个目录
#define    S_IFCHR     0020000   文件是一个特殊的字符设备
#define    S_IFIFO       0010000   文件是一个FIFO设备
#define    S_IFREG     0100000   文件是一个普通文件
#define    S_FLNK      0120000   文件是一个符号链接


if ((infobuf.st_mode & S_IFMT) == S_IFDIR)


辅助确定文件类型的宏定义
S_ISBLK      测试是否是特殊的块设备文件
S_ISCHR      测试是否是特殊的字符设备文件
S_ISDIR       测试是否是目录
S_ISFIFO     测试是否是FIFO设备
S_ISREG      测试是否是普通文件
S_ISLNK      测试是否是符号链接文件




lseek:


unistd.h
sys/types.h


off_t lseek(int fd, off_t offset, int start_flags);//改变已打开文件的位置


offset标识新位置相对起始位置的字节数
start_flags参数含义:SEEK_SET offset是从文件的起始位置开始算,通常值为0
    SEEK_CUR offset相对文件读写的当前位置开始算,通常值为1
    SEEK_END offset相对文件尾而言,通常值为2




通过用户ID得到用户信息:
pwd.h


struct passwd *getpwuid(uid_t uid); //成功返回passwd结构体指针,否则返回NULL
 struct passwd
 {
        char *pw_name;       //用户名
        char *pw_passwd;    //用户密码
        uid_t pw_uid;            //用户ID
        gid_t pw_gid;            //用户所在组ID
        char *pw_gecos;       //真实名字
        char *pw_dir;            //用户主目录
        char *pw_shell          //用户所用Shell
  };




通过用户组ID得到用户组信息
grp.h


struct group *getgrgid(gid_t gid); //成功返回结构体指针,否则返回NULL
struct group
{
        char *gr_name;             //组名
        char *gr_passwd;          //组密码
        gid_t gr_gid;                  //组ID
        char **gr_mem;             //组成员列表
};






chmod:
sys/stat.h


int chmod(const char *path, mode_t mode);


int fchmod(int fd, mode_t mode);


chown:
unistd.h


int chown(const char *path, uid_t owner, gid_t group);\\改变文件或目录的所有者或组




link:
unistd.h


int unlink(const char *pathname);
int link(const char *path1, const char *path2);
int symlink(const char *path1, const char *path2);
int readlink(char *pathname,char *buf, int bufsize);
<think>好的,用户想了解Linux文件IO操作或者解决相关问题,需要教程或常见问题解决方案。首先,我需要整理一下相关的知识点,确保覆盖文件IO的基本操作、常见问题以及解决方法。根据用户提供的引用内容,尤其是引用4和引用5,里面提到了文件共享、打开方式、重定位等,这些都需要详细解释。 首先,应该从基础的文件操作开始,比如打开、读写、关闭文件。用户可能对系统调用如open、read、write、close不太熟悉,需要解释这些函数的使用方法,包括参数和返回值。同时,要提到文件描述符的概念,这是Linux文件IO的核心。 接下来,关于文件共享的三种方式,引用4中已经提到,我需要详细展开,说明不同进程如何共享文件,以及dup和dup2的作用。这部分可能涉及到文件描述符的复制,以及重定向的原理,如引用2中的重定位符号>的实现,这里可以结合例子说明。 然后,常见问题方面,用户可能会遇到权限问题、文件锁定、大文件处理等。比如,打开文件时权限不足,或者多个进程同时写入导致数据混乱。这时候需要讲解如何正确设置文件权限,使用flock或者fcntl进行文件锁定,以及处理大文件时使用O_LARGEFILE标志。 另外,用户提供的引用2和引用3提到了重定位和IO操作的条件,这部分可以解释输入输出重定向的原理,比如使用dup2系统调用实现,以及非阻塞IO的相关问题。可能用户在实际操作中遇到重定向失败或者IO阻塞的情况,需要给出解决方案。 还要考虑不同模式下的文件操作,如阻塞与非阻塞模式的区别,如何设置非阻塞模式,以及这些模式对读写操作的影响。引用3提到发起IO操作的条件,如果无法立即完成则报错,这可能与非阻塞模式有关,需要说明清楚。 在代码示例方面,用户可能需要实际的代码片段来理解如何操作。比如,使用open打开文件,并处理错误;使用read和write进行文件读写,并检查返回值;使用dup2实现重定向等。同时,需要强调错误处理的重要性,比如检查系统调用的返回值,避免程序崩溃。 关于文件位置指针的问题,用户可能在追加写入或随机访问时遇到问题,需要解释lseek函数的使用,以及O_APPEND标志的作用,确保写入位置正确。 最后,生成相关问题时要围绕用户可能进一步询问的方向,比如文件锁的具体使用、非阻塞IO的应用场景、文件描述符的复制方法等,这样可以帮助用户深入理解。 现在需要将以上思考整理成一个结构清晰的回答,分点讲解,结合引用中的内容,并附上代码示例和问题解决方案。注意使用正确的LaTeX格式,行内公式用$,独立公式用$$,同时确保引用标识正确添加在对应的位置。</think>### Linux 文件 IO 操作教程 #### 一、基础操作 1. **文件打开与关闭** 使用系统调用 `open()` 打开文件,返回文件描述符(fd)。需指定路径和模式(如只读、只写、追加等)。示例: ```c int fd = open("test.txt", O_RDWR | O_CREAT, 0644); // 创建或打开文件,权限644 if (fd == -1) { perror("open failed"); exit(1); } close(fd); // 关闭文件 ``` 模式参数如 `O_RDONLY`(只读)、`O_WRONLY`(只写)可通过位或组合[^4]。 2. **读写操作** - `read(fd, buf, size)`:从文件描述符读取数据到缓冲区。 - `write(fd, buf, size)`:将缓冲区数据写入文件。 示例: ```c char buf[1024]; ssize_t bytes_read = read(fd, buf, sizeof(buf)); // 返回实际读取字节数 if (bytes_read == -1) { /* 错误处理 */ } ``` #### 二、文件共享与描述符复制 1. **共享方式** - 同一进程多次 `open()` 同一文件。 - 不同进程分别 `open()` 同一文件。 - 使用 `dup()` 或 `dup2()` 复制描述符。 示例通过 `dup2` 实现输出重定向到文件: ```c int new_fd = open("output.txt", O_WRONLY | O_CREAT, 0644); dup2(new_fd, STDOUT_FILENO); // 将标准输出重定向到文件 ``` 2. **重定位原理** Shell 中的 `>` 符号通过 `open()` + `close()` + `dup()` 实现,将文件关联到标准输出描述符[^2]。 #### 三、常见问题与解决方案 1. **权限不足** - 检查文件权限:`ls -l` 查看权限,使用 `chmod` 修改。 - 确保 `open()` 调用时正确设置模式参数(如 `O_CREAT` 需指定权限)。 2. **并发写入冲突** - 使用文件锁(`flock()` 或 `fcntl()`): ```c struct flock lock = {F_WRLCK, SEEK_SET, 0, 0, getpid()}; fcntl(fd, F_SETLKW, &lock); // 阻塞式加锁 ``` 3. **大文件处理** - 编译时添加 `-D_FILE_OFFSET_BITS=64`,或使用 `O_LARGEFILE` 标志。 #### 四、进阶操作 1. **非阻塞模式** 设置 `O_NONBLOCK` 标志: ```c int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK); if (fd == -1) { /* 处理错误 */ } ``` 若当前无法立即完成 IO,操作会返回 `EAGAIN` 错误[^3]。 2. **文件位置指针** 使用 `lseek(fd, offset, whence)` 调整读写位置。例如追加写入: ```c lseek(fd, 0, SEEK_END); // 移动到文件末尾 write(fd, "new data", 8); ``` 或直接通过 `O_APPEND` 标志实现原子追加[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值