[Linux operating system] In-depth understanding of the read and write functions in system calls

In the operating system, the system call is an important way of interaction between the user program and the operating system. Among them, the read and write functions are commonly used system call functions for reading and writing data between the user program and the operating system. This article will give an in-depth introduction to the working principle, usage and sample code of the read and write functions to help readers better understand and apply these two functions.
insert image description here

1. The working principle and usage of the read function:

1.1 Function prototype and parameters

The read function is used to read data from the file descriptor and store the data in the buffer.

Its function prototype is as follows:

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

Among them, fdis the file descriptor, bufis the buffer for storing the read data, and countis the number of bytes to be read. readThe function returns the number of bytes actually read, if it returns -1 , it means the read failed.

Explanation from the official manual:
 
insert image description here

1.2 Code example

Here is a sample code that uses the read function to read data from a file:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    
    
    int fd = open("file.txt", O_RDONLY);
    char buffer[1024];
    ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
    if (bytesRead == -1) {
    
    
        perror("read");
        return 1;
    }
    printf("Read %ld bytes: %s\n", bytesRead, buffer);
    close(fd);
    return 0;
}

1.3 Code Explanation

In the sample code above, opena function is first used to open a file.txtfile named read-only. Then, readthe function reads the data from the file, stores the data into it buffer, and finally printfoutputs the read data through the function.

2. The working principle and usage of the write function:

2.1 Function prototype and parameters

The write function is used to write data from the buffer to the file descriptor.

Its function prototype is as follows:

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

Among them, fdis the file descriptor, bufis the buffer that stores the data to be written, and countis the number of bytes to be written. writeThe function returns the number of bytes actually written. If it returns -1 , it means that the writing failed.

Explanation from the official manual:

insert image description here

2.2 Code example

Here is a sample code that writes data to a file using the write function:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    
    
    int fd = open("file.txt", O_WRONLY | O_CREAT, 0644);
    char *data = "Hello, world!";
    ssize_t bytesWritten = write(fd, data, strlen(data));
    if (bytesWritten == -1) {
    
    
        perror("write");
        return 1;
    }
    printf("Written %ld bytes\n", bytesWritten);
    close(fd);
    return 0;
}

2.3 Code Explanation

In the sample code above, opena function is first used to create a file.txtfile named and opened for writing only. Then, writethe function "Hello, world!"writes the string to the file, and finally printfthe function outputs the number of bytes written.

3. File descriptors

3.1 Process control block

Process Control Block (PCB) is a data structure used to manage and control processes in the operating system. Each process that is running or waiting to run has a corresponding PCB, which contains various attributes and status information of the process.

PCB is usually a data structure that contains the following information:

  1. Process Identifier (Process Identifier, PID) : Used to uniquely identify a process.
  2. Program Counter (Program Counter, PC) : Records the address of the next instruction to be executed.
  3. Register collection : including general-purpose registers, instruction registers, stack pointers, etc., used to save the context information of the process.
  4. Process State (Process State) : Indicates the current state of the process, such as running, ready, waiting, etc.
  5. Process Priority : Used to determine the priority order of processes when scheduling.
  6. Process scheduling information : including process scheduling policy, time slice size, etc.
  7. Process resource management information : including resources owned by the process, open files, etc.
  8. Parent Process Identifier (Parent Process Identifier, PPID) : Records the PID of the parent process that created the process.
  9. Process creation time and running time : Records the process creation time and running time.
  10. Memory management information : including process memory allocation, page table, etc.
  11. File descriptor table : records the files opened by the process and the corresponding file descriptors.

PCB is a very important data structure in the operating system, which stores all the key information of the process, so that the operating system can manage and schedule the process. When the operating system needs to switch processes, it will save the context information of the current process to its corresponding PCB, and load the context information of the next process. This enables process switching and concurrent execution.

3.2 What is a file operator

A file descriptor can be thought of as an identifier assigned by the operating system to manage open files or devices . It is an integer value used to identify a specific file or device.

Imagine that you have opened a file or device in your operating system, such as a text file or a serial device. The operating system allocates a file descriptor for this file or device and returns it to you. This file descriptor is like a house number, which is used to mark this file or device .

When you want to perform 读取, 写入or, 关闭etc. operations on this file or device, you only need to tell the operating system to use this file descriptor, and the operating system will know which file or device you want to operate.

The specific value of the file descriptor is a non-negative integer, usually starting from 0 and incrementing. The operating system uses a file descriptor table to record information about all open files or devices, including file locations, read and write permissions, and more. When you use a file descriptor to operate, the operating system will find the corresponding file information according to the file descriptor and perform corresponding operations.

insert image description here

3.3 Special file descriptors

  1. Standard Input (Standard Input, STDIN): The standard input file descriptor, usually represented by the integer value 0; in the C language, a macro definition can be used STDIN_FILENOto represent the standard input. It is used to receive user input, such as keyboard input.
#include <unistd.h>

int main() {
    
    
    char buffer[100];
    ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer));
    // 从标准输入读取数据
    // ...
    return 0;
}
  1. Standard Output (Standard Output, STDOUT): Usually represented by the integer value 1. In C language, you can use macro definition STDOUT_FILENOto represent standard output. It is used to output information to the screen or terminal.
#include <unistd.h>

int main() {
    
    
    char buffer[] = "Hello, World!";
    ssize_t bytesWritten = write(STDOUT_FILENO, buffer, sizeof(buffer));
    // 将数据输出到标准输出
    // ...
    return 0;
}
  1. Standard Input (Standard Input, STDIN): Usually represented by the integer value 2. In C language, you can use macro definition STDERR_FILENOto represent standard error. It is used to receive user input, such as keyboard input.
#include <unistd.h>
#include <stdio.h>

int main() {
    
    
    fprintf(stderr, "An error occurred!\n");
    // 输出错误信息到标准错误
    // ...
    return 0;
}

Guess you like

Origin blog.csdn.net/Goforyouqp/article/details/132186579