当前位置:   article > 正文

linux文件操作——基于unix标准库函数(open、read、write函数等)_open是linux标准库函数吗

open是linux标准库函数吗

1. 前言

linux系统中,“一切皆文件”这一观点非常重要,也就是说无论执行什么类型的操作,都可以用 “打开 open->读写 read/write->关闭 close”模式来操作。
大多数情况下,我们只需要使用五个基本的库函数——open、close、read、write和ioctl。

2. Linux文件结构

2.1目录

目录除了本身包含的内容外,还会有一个名字和一些属性,即“管理信息”,例如:利用ls -l在当前目录下执行,可以得到如下图所示
在这里插入图片描述

红色框线圈出的就是文件名字和对应文件属性。

2.2文件和设备

硬件设备在linux操作系统中通常也被表示为文件。
在linux中比较重要的设备文件有三个——/dev/console、/dev/tty和dev/null。

  1. /dev/console
    这个设备代表的是系统控制台。错误信息和诊断信息通常会被发送到这个设备。

  2. /dev/tty
    如果一个进程有控制终端,那么特殊文件/dev/tty就是这个控制终端(键盘和显示屏,或键盘和窗口)的别名(逻辑设备)。

  3. /dev/null
    这是空(null)设备。所有写向这个设备的输出都将被丢弃。而读这个设备会立刻返回一个文件尾标志,所以在cp命令中可以把它用做拷贝空文件的源文件。

3.unix库函数的IO操作

在输入输出操作中,直接使用底层系统调用会使效率非常低,所以linux/unix提供了一系列标准函数库,一般在<unistd.h>头文件中。
每个运行中的程序被称为进程,它有一些与之关联的文件描述符。可以通过他们访问打开的文件或设备。
当开始运行程序时,一般会有三个已经打开的文件描述符。

  • 0:标准输入
  • 1:标准输出
  • 2:标准错误
3.1 write函数

系统调用write的作用是,把缓冲区buf的前count个字节写入与文件描述符fildes关联的文件中。它返回实际写入的字节数。如果返回0,则表示未写出任何数据,如果是-1,则表示write调用出错,对应的错误代码保存在全局标量errono里面。

调用原型如下:(可以使用man 2 write在linux系统中查看write函数的帮助页)

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count); 
  • 1
  • 2
  • 3

来个demo试试:

#include <unistd.h>
#include <stdlib.h>

int main()
{
    if(write(1, "Here is some data\n", 18) != 18)       // 人为设定必须写入18个字节
        write(2, "A write error has occurred on file descriptor 1\n", 46);
        
    exit(1);        // 与return 0;的作用一样
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3.2 read函数

系统调用read的作用是,把缓冲区buf的前count个字节读入与文件描述符fildes关联的文件中。它返回实际读入的字节数。如果返回0,则表示未读出任何数据,如果是-1,则表示write调用出错,对应的错误代码保存在全局标量errono里面。

调用原型如下:(可以使用man 2 read在linux系统中查看read函数的帮助页)

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
  • 1
  • 2
  • 3

来个demo试试:

#include <unistd.h>
#include <stdlib.h>
   
int main()
{
    char buffer[20];		// 定义一个存储标准输入的缓冲区,大小为20个字节
    int nread;				// 存储read函数返回值

     nread = read(0, buffer, 10);
     if(nread == -1)
     {
         write(2, "a read error!\n", 14);		// 打印出读取错误
     }
     if(write(1, buffer, nread) != nread)		// 输出读取的字符串
         write(2, "write error!\n", 13);		// 输出错误

     return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
3.3open系统调用

同样用man 2 open打开open函数的帮助页,可以看到如下所示帮助信息:

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

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

打开文件成功返回0,否则返回-1,并设置全局变量errno以指明失败的原因。
需要说明的是,参数flags表示打开文件所采取的动作,而mode是表示文件的权限,也可以单独用chmod函数来设定。
下面介绍一下flags参数最常用的模式:

模式说明
O_RDONLY以只读方式打开
O_WRONLY以只写方式打开
O_RDWR以读写方式打开
O_APPEND把写入数据追加在文件的末尾
O_CREAT如果需要,就按参数mode给出的访问模式创建文件
O_EXCL与O_CREAT一起使用,确保调用者创建出文件。open是一个原子操作,也就是说,它只执行一个函数调用。使用这个可选模式可以防止两个程序同时创建一个文件,如果文件存在,open调用将失败 。

下面说一下参数mode,就不多解释,下图所示,输入对应的数字就好,当然也可以叠加,比如700表示所有者可以读写和执行。

在这里插入图片描述

3.4 close函数

close函数调用终止一个文件描述符fd与其对应文件之间的关联。
close调用成功就返回0,出错就返回-1.

#include <unistd.h>

int close(int fildes);
  • 1
  • 2
  • 3
3.5 ioctl函数调用

ioctl调用有点像是一个大袋子。它提供了一个用于控制设备及其描述符行为和配置底层服务的接口。
终端、文件描述符、套接字甚至磁带机都可以有为它们定义的ioctl。

#include <unistd.h>

int ioctl(int fd, int cmd, ...);
  • 1
  • 2
  • 3
3.6其他系统调用函数
  1. lseek函数:对文件描述符fd的读写指针进行设置,可以用来设置文件的下一个读写位置。
#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
  • 1
  • 2
  • 3
  • 4

其中offset表示偏移值,whence表示偏移值的用法,有SEEK_SET(绝对位置),SEEK_CUR(相对位置),SEEK_END(相对于文件尾的相对位置)

  1. fstat、stat和lstat函数
    返回与打开的文件描述符相关的文件状态信息,该信息将写到buf结构中。
    详情请见man帮助页

  2. dup和dup2函数

该函数调用提供了复制文件描述符的一种方法,是我们能够通过两个或者更多个不同的描述符来访问同一个文件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/256378
推荐阅读
相关标签
  

闽ICP备14008679号