Linux —— 基础I/O(一)

目录

一,背景介绍

二,系统接口函数

open 打开或创建文件

close 关闭文件

read 读取文件

write 写入文件

三,文件描述符

结构体指针files

结构体指针files指向的表files_struct

文件结构体


一,背景介绍

        狭义的文件存放在磁盘上,广义上在Linux下一切皆文件;磁盘上的文件一般为永久存储的外设,本质上对文件的操作,即为对外设的输入和输出(简称I/O);空文件并不是不占磁盘文件,只是没有内容,文件=属性(元数据)+内容;对文件的内容操作,如fread、fwrite、fgets、fgetc,fputc,fputs等;对文件的属性操作,如fseek、ftell、rewind等;

        从系统角度,对文件的操作,其实就是进程对文件的操作;是通过系统调用接口,来实现操作的;

当前路径,每个进程都有一个内置属性cwd(即当前工作目录);

[wz@192 ~]$ ll /proc/29286
total 0
dr-xr-xr-x. 2 wz wz 0 8月   7 19:11 attr
-rw-r--r--. 1 wz wz 0 8月   7 19:11 autogroup
-r--------. 1 wz wz 0 8月   7 19:11 auxv
-r--r--r--. 1 wz wz 0 8月   7 19:11 cgroup
--w-------. 1 wz wz 0 8月   7 19:11 clear_refs
-r--r--r--. 1 wz wz 0 8月   7 19:10 cmdline
-rw-r--r--. 1 wz wz 0 8月   7 19:11 comm
-rw-r--r--. 1 wz wz 0 8月   7 19:11 coredump_filter
-r--r--r--. 1 wz wz 0 8月   7 19:11 cpuset
lrwxrwxrwx. 1 wz wz 0 8月   7 19:11 cwd -> /home/wz/Desktop
-r--------. 1 wz wz 0 8月   7 19:11 environ
lrwxrwxrwx. 1 wz wz 0 8月   7 19:11 exe -> /home/wz/Desktop/target
dr-x------. 2 wz wz 0 8月   7 19:10 fd
...

 在任何C程序,都会默认打开三个文件(硬件):

  • 标准输入,stdin,键盘文件;
  • 标准输出,stdout,显示器文件;
  • 标准错误,stderr,显示器文件;

Linux —— 基础I/O(一)_第1张图片

注,所有外设硬件,本质上即对应read/write的核心操作;可通过C接口,直接对stdin/stdout/stderr进行读写操作;默认打开这三个文件,其他函数使用需求,如scanf、printf、perror等,另外fprintf、fscanf;其他语言也是如此,C++中是cin、cout、cerr;

Linux —— 基础I/O(一)_第2张图片

Linux —— 基础I/O(一)_第3张图片

二,系统接口函数

        open、close、read、write;

open 打开或创建文件

Linux —— 基础I/O(一)_第4张图片

close 关闭文件

Linux —— 基础I/O(一)_第5张图片

read 读取文件

Linux —— 基础I/O(一)_第6张图片

write 写入文件

Linux —— 基础I/O(一)_第7张图片

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    const char* msg = "hello world\n";
    write(fd, msg, strlen(msg));
    close(fd);
    return 0; 
}
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd = open("log.txt", O_RDONLY);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    char buffer[1024];
    ssize_t s = read(fd, buffer, sizeof(buffer)-1);
    if(s>0)
    {
        buffer[s] = '\0';
        printf("%s\n", buffer);
    }
    close(fd);
    return 0; 
}
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd = open("log.txt", O_WRONLY|O_APPEND);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    const char* msg = "hello world append\n";
    write(fd, msg, strlen(msg));
    close(fd);
    return 0; 
}

注:

  • O_WRONLY|O_CREAT 对应C语言 w ;
  • O_RDONLY 对应C语言 r ;
  • O_WRONLY|O_APPEND 对应C语言 a ;

标签flags,O_WRONLY、O_CREAT、O_RDONLY、O_APPEND都是宏;

/usr/include/asm-generic/fcntl.h

#define O_ACCMODE 00000003
#define O_RDONLY  00000000
#define O_WRONLY  00000001
#define O_RDWR    00000002
#ifndef O_CREAT
#define O_CREAT   00000100  /* not fcntl */
#endif
#ifndef O_EXCL
#define O_EXCL    00000200  /* not fcntl */
#endif
#ifndef O_NOCTTY
#define O_NOCTTY  00000400  /* not fcntl */
#endif
#ifndef O_TRUNC
#define O_TRUNC   00001000  /* not fcntl */
#endif
#ifndef O_APPEND                                                                 
#define O_APPEND  00002000
#endif

        编程语言使用自己的接口,封装系统接口,是因为需兼容自身语法特征,且系统调用使用成本较高,不具备可移植性;

三,文件描述符

        Linux进程默认会有三个已打开的文件描述符,即0(stdin键盘)、1(stdout显示器)、2(stderr显示器);系统接口函数的返回值即为文件描述符,是从0开始的小整数,实际上是数组的下标;新文件的文件描述符使用当前没被使用的最小下标;

#include       
#include       
#include       
#include       
#include       
#include    

int main()      
{      
    int fd1 = open("log1.txt", O_WRONLY|O_CREAT, 0644);      
    int fd2 = open("log2.txt", O_WRONLY|O_CREAT, 0644);      
    int fd3 = open("log3.txt", O_WRONLY|O_CREAT, 0644);      
    int fd4 = open("log4.txt", O_WRONLY|O_CREAT, 0644);      
      
    printf("fd1=%d\n",fd1);  
    close(fd1);    
    printf("fd2=%d\n",fd2);                                                          
    printf("fd3=%d\n",fd3);      
    printf("fd4=%d\n",fd4);      
    return 0;       
}   
//新建的文件会从3开始
[wz@192 Desktop]$ ./target 
fd1=3
fd2=4
fd3=5
fd4=6

结构体指针files

  • 进程task_struct包含一个结构体指针files;

结构体指针files指向的表files_struct

  • 该表包含一个结构体指针数组;
  • 该数组中元素指向打开的文件;

Linux —— 基础I/O(一)_第8张图片

文件结构体

Linux —— 基础I/O(一)_第9张图片

Linux —— 基础I/O(一)_第10张图片

Linux —— 基础I/O(一)_第11张图片

你可能感兴趣的:(操作系统,linux)