系统级I/O

本文介绍了Linux系统中一切皆文件的理念,详细讲解了不同类型的文件、统一的I/O执行方式,包括文件打开、读写、关闭的过程。还重点阐述了I/O重定向中的dup2函数,展示了其如何复制文件描述符并影响进程的读写行为。
摘要由CSDN通过智能技术生成

系统级I/O

我们应该要清楚的很重要的一句话:Linux中一切皆文件

Linux文件类型
  • 普通文件
  • 目录文件
  • 套接字文件
输入输出统一且一致的执行方式
  • 打开文件
  • Linux shell 创建的每个进程开始时都有三个打开 的文件:标准输入(描述符为0)、标准输出(1)、标准错误(2)
  • 改变当前的文件位置
  • 读写文件
  • 关闭文件

内核用三个相关的数据结构来表示打开的文件

  • 进程表:内核维护一张进程表,记录每一个进程项,进程项中维持了一张在该进程中所有的打开的文件描述符,每个文件描述符记录了问价描述符标志和文件表项。
  • 文件表:内核维护一张文件表,用来记录所有的打开的文件表项。每个文件表项记录文件描述符状态标记、文件指针当前偏移量以及指向文件v节点所在地址的指针。
  • v节点表:同文件表一样,所有进程共享这张v节点表,每个表项包含stat结构中的大多数信息

文件共享
在这里插入图片描述
没有文件共享

在这里插入图片描述

open函数

进程是通过调用open函数来打开一个已经存在的文件或者创建一个新文件的

#include <sys/types.h>
#include <sys/stat.h> 
#include <fcntl.h> 
int open(char *filename, int flags, mode_t mode); 

open函数将filename转换为一个文件描述符,并且返回描述符数字,返回的描述符总是在进程中当前没有打开的最小描述符
flags参数

  • O_RDONLY:只读
  • O_WRONLY:只写
  • O_RDWY:可读可写

mode参数
指定了新文件的访问权限,根据不同权限信息&、|操作赋予文件不同的权限
访问权限:可读(二进制100)、可写(010)、可执行(001)

在这里插入图片描述

实验

#include <sys/types.h>
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio>
int main ()
{
int fd;
fd=open("a.txt",O_RDONLY,0);
printf("fd=%d\n",fd);
return 0;
}

结果
fd=3
标准输入0,标准输出1,错误2,现在最小的文件描述符为3,所以输出3

close函数
手动关闭打开的进程描述符,成功返回0,否则返回-1

int close(int fd);

read函数
读文件

ssize_t read(int fd,void *buf,size_t n);

write函数
写文件

ssize_t write(int fd,const void *buf,size_t n);

I/O重定向 dup2函数

复制描述符表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前 的内容,如果newfd已经打开了,dup2会在复制oldfd之前关闭newfd

#include <unistd.h>
int dup2 (int oldfd,int newfd);

在这里插入图片描述

实验

#include "csapp.h"

int main(int argc, char *argv[])
{
    int fd1, fd2, fd3;
    char c1, c2, c3;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    fd2 = Open(fname, O_RDONLY, 0);
    fd3 = Open(fname, O_RDONLY, 0);
    dup2(fd2, fd3);

    Read(fd1, &c1, 1);
    Read(fd2, &c2, 1);
    Read(fd3, &c3, 1);
    printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);

    Close(fd1);
    Close(fd2);
    Close(fd3);
    return 0;
}

结果
在这里插入图片描述
fd2替换掉了fd3,对fd3的操作实际上是对fd2的操作

#include "csapp.h"

int main(int argc, char *argv[])
{
    int fd1;
    int s = getpid() & 0x1;
    char c1, c2;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    Read(fd1, &c1, 1);
    if (fork()) {
	/* Parent */
	sleep(s);
	Read(fd1, &c2, 1);
	printf("Parent: c1 = %c, c2 = %c\n", c1, c2);
    } else {
	/* Child */
	sleep(1-s);
	Read(fd1, &c2, 1);
	printf("Child: c1 = %c, c2 = %c\n", c1, c2);
    }
    return 0;
}

结果

在这里插入图片描述
由于父子进程共享的是一个文件,子进程读取之后光标移向下一位置,父进程进来读,因此父进程中c2=c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值