Linux—系统(I/O)

17 篇文章 1 订阅

1.系统接口

1.1 打开文件open()

  • int open(const char *pathname, int flags);
  • int open(const char *pathname, int flags, mode_t mode);
    参数:pathname带路径文件名;flags文件的打开方式;mode文件的权限。
    返回值:打开文件成功,返回新打开的文件的文件描述符,失败则返回-1。

flags文件的打开方式:

  1. O_RDONLY: 只读打开
  2. O_WRONLY: 只写打开
  3. O_RDWR : 读,写打开
  • 这三个常量,必须指定一个且只能指定一个。
  1. O_CREAT : 若文件不存在,则创建它。
  2. O_TRUNC: 覆盖写(每次写入删除原内容,将本次内容写入)。
  3. O_APPEND: 追加写(每次写入不删除原内容,将本次内容写入)。
  • 用上面的1,2,3和下面的1,2,3 的一个或者多个常量进行“或”运算。
  • 例:O_WRONLY | O_CREAT。

1.2 关闭文件close()

  • int close(int fd);
    参数:要关闭的文件的文件描述符。
    返回值:成功返回0,失败返回-1。

1.3 读/写文件 write()/read()

1.3.1读文件write()

  • ssize_t write(int fd, const void *buf, size_t count);
    参数:fd文件描述符;buf写入的字符串;count写入的大小。
    返回值:成功返回写入成功的字节数,失败返回-1。

1.3.2 写文件read()

  • ssize_t read(int fd, void *buf, size_t count);
    参数:fd文件描述符;buf输出型参数,保存读出的内容;count读取的大小
    返回值:成功返回读取成功的字节数,失败返回-1

1.4 代码示例:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#define SIZE 128

int main()
{
  //close(1);
  int fd = open("log.txt",O_CREAT|O_APPEND|O_RDWR,0644); //打开文件
  if(fd<0)
  {
      perror("open error!");
      return 1;
  }


 // const char* str1="Hello World 2!\n";
 //  write(fd,str1,strlen(str1));  //写文件 1
  
  char buf[SIZE]={0};
  read(fd,buf,15); //读文件
  printf("buf = %s",buf);

  close(fd); //关闭文件

  return 0;
  }

运行结果:
写文件 1:
在这里插入图片描述
读文件 1:
在这里插入图片描述

2.open函数返回值

在认识返回值之前,先来认识一下两个概念: 系统调用库函数

  • 上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。
  • open close read write lseek 都属于系统提供的接口,称之为系统调用接口。

2.1 文件描述符fd

  • 通过对open函数的学习,我们知道了文件描述符就是一个小整数。

0 & 1 & 2

  • Linux进程默认情况下会有3个缺省打开的文件描述符。
  • 分别是标准输入0。物理设备:键盘
  • 标准输出1。 物理设备:显示器
  • 标准错误2。 物理设备:显示器

打开文件操作需要进程调用open系统调用,因此必须让进程和文件关联起来,每一个进程都由一个file* 指针指向一张表files_struct,而这个结构体中最重要的一部分就是一个结构体指针数组file* fd_array[],这个数组中存放了当前进程所访问的所有文件,而文件描述符就是这个数组的下标。

在这里插入图片描述

2.2文件描述符的分配原则

  • 在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。一般文件描述符从3开始,因为0,1,2 都被占用了。在每个文件打开时 0,1,2被占用了。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
	int fd = open("myfile", O_RDONLY);
	if(fd < 0){
	perror("open");
	return 1;
}
	printf("fd: %d\n", fd);
	close(fd);
	return 0;
}

在这里插入图片描述

3.重定向

  • 本来应该输出到显示器上的内容,输出到了文件当中,其中,fd=1。这种现象叫做输出重定向。常见的重定向有: >, >>, <。

代码示例:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#define SIZE 128

int main()
{
  close(1);
  int fd = open("log.txt",O_CREAT|O_TRUNC|O_RDWR,0644);
  if(fd<0)
  {
      perror("open error!");
      return 1;
  }


  const char* str="Hello World 1!\n";
  const char* str1="Hello World 2!\n";
  const char* str2="Hello World 3!\n";
  write(1,str,strlen(str));
  printf(str1);
  fprintf(stdout,str2);

  fflush(stdout);
  close(fd);

  return 0;
}

在这里插入图片描述

由运行结果可得,原本应该输入到显示器上的 Hello World 1!,Hello World 2!,Hello World 3!在程序运行以后,并没有输出出来,那去哪里了呢

  1. 因为close(1),在files_struct中下标 1 代表标准输出1关闭了1以后按照文件描述符的分配原则可知,fd此时为1,则将本来应该输出到显示器上的内容输出到了文件log.txt中。看下图查看log.txt中的内容证明:
    在这里插入图片描述
    那么什么是重定向的本质呢?
    在这里插入图片描述
  2. 由上面 close(1)的方式实现重定向难免太挫,这时候就要来把dup2()介绍出来了。

3.1 dup2()

  • int dup2(int oldfd, int newfd);
    头文件:#include <unistd.h>
  1. dup2可以用参数newfd指定新文件描述符的数值 若参数newfd已经被程序使用,则系统就会将newfd所指的文件关闭。
  2. 若newfd等于oldfd,则返回newfd,而不关闭newfd所指的文件。
  3. dup2所复制的文件描述符与原来的文件描述符共享各种文件状态。共享所有的锁定,读写位置和各项权限或flags等。

代码示例:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#define SIZE 128

int main()
{

  int fd = open("log.txt",O_CREAT|O_TRUNC|O_RDWR,0644);
  if(fd<0)
  {
      perror("open error!");
      return 1;
  }

  const char* str1="Hello World 2!\n";
  write(fd,str1,strlen(str1));
  dup2(fd,1);
  printf(str1);
  
  fflush(stdout);
  close(fd);

  return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
由上图两个运行结果可得和上面的close(1)重定向的效果一摸一样。

3.2 dup2()原理

  • 当我们调用它的时候,dup会返回一个新的描述符,这个描述一定是当前可用文件描述符中的最小值。我们知道,一般的0,1,2描述符分别被标准输入、输出、错误占用,所以在程序中如果close掉标准输出1后,调用dup函数,此时返回的描述符就是1。对于dup2,可以用fd2指定新描述符的值,如果fd2本身已经打开了,则会先将其关闭。如果fd等于fd2,则返回fd2,并不关闭它。这两个函数返回的描述符与fd描述符所指向的文件共享同一文件表项。相当于把原本1的位置用新的文件覆盖掉。则下标1此时就指向新文件。如下图所示:

在这里插入图片描述

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值