[System Call] Commonly used system call functions: detailed introduction

Table of contents

0. System call concept

1. Commonly used system call functions 

1.1 open function

1.2 perror, error function

1.3 close function

1.4 write function

1.5 read function

1.6 stat function

1.7 dup, dup2 function

1.8 fcntl function

2. Other I/O functions

2.1 access function

2.2 chmod function

2.3 chown function

2.4 truncate function

2.5 link function

2.6 symlink function

2.7 readlink function

2.8 unlink function

2.9 rename function

3. Directory related functions

3.1 getcwd function

3.2 chdir function

3.3 opendir function

3.4 closedir function

3.5 readdir function

Summarize:


0. System call concept

Operating system responsibilities

        The operating system manages all resources and associates different devices with different programs.

What is Linux system programming

        Program in an operating system environment and use system calls and various libraries provided by the operating system to access system resources.

System programming is mainly to enable users to operate hardware devices better and more conveniently, and also to protect hardware devices. The essence of the programs we write is to operate hardware devices, so the operating system provides interfaces to operate hardware.

System call overview:

        The essence is to operate hardware devices, but the Linux operating system has a kernel on top of the hardware, that is, only the kernel can directly operate hardware devices. If you want to operate the kernel, you need to call the system call of the kernel. If you want to operate the kernel There are three ways to call the system:

  • The first type: shell, the user uses shell commands, and the shell interpreter operates the system calls of the kernel.
  • The second type: library function, the user operates the kernel system call through the interface of the application layer library function, such as fread.
  • The third type: application layer system call, which can directly operate on the kernel system call.

System calls are a set of "special" function interfaces provided by the operating system to user programs.

Different versions of Linux provide between two and three hundred system calls.

User programs can obtain services provided by the operating system (kernel) through this set of interfaces.

 System calls can be roughly divided into following functional logic:

        Process control, inter-process communication, file system control, system control, memory management, network management, socket control, user management.

Return value of system call:

        Typically, a non-negative return value is used to indicate error, and a 0 value is used to indicate success.

        The error information is stored in the global variable errno, and the user can use the perror function to print the error information.

Specifications followed by system calls:

        In Linux, the application programming interface (API) follows the POSIX standard.

System call I/O function

File descriptor:

        File descriptors are nonnegative integers. When opening an existing file or creating a new file, the system (kernel) returns a file descriptor. The file descriptor is used to specify the opened file.

        In system calls (file IO), file descriptors play a role in identifying files. If you want to operate a file, you must operate on the file descriptor.

When a program runs or a process is started, the system automatically creates three file descriptors.

  • #define STDIN_FILENO 0 //Standard input file descriptor
  • #define STDOUT_FILENO 1 //File descriptor of standard output
  • #define STDERR_FILENO 2 //Standard error file descriptor

If you open the file yourself, the file descriptor will be returned, and the file descriptors are generally created in order from small to large.

1. Commonly used system call functions 

1.1 open function

#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);

Function:

        Open the file on your behalf. If the file does not exist, you can choose to create it.

parameter:

        pathname: The path and file name of the file.

        flags: Behavior flags for opening files, required options O_RDONLY, O_WRONLY, O_RDWR

        mode: This parameter is only valid when the file does not exist. It refers to specifying the permissions of the file when creating a new file.

return value:

        Success: file descriptor

        Failure: -1

flags detailed description

required:

value meaning
O_RDONLY Open as read-only
O_WRONLY Open as write-only
O_RDWR Open for reading and writing

Options:

value meaning
O_CREATE If the file does not exist, create the file, which must be followed by mode (usually 0664)
O_EXCL If O_CREAT is also specified and the file already exists, an error occurs.
O_TRUNC If the file exists, clear the file contents
O_APPEND When writing a file, data is added to the end of the file
O_NONBLOCK

For device files, opening them in O_NONBLOCK mode can do non-blocking I/O.

Supplementary instructions for mode:

1) Final file permissions: mode & ~umask

2) The umask mask of the shell process can be viewed using the umask command.

umask: View mask (complement)

umask mode: Set the mask, mode is an octal number

umask -S: View the default operation permissions of each group of users

Comparison of file I/O and standard I/O permissions:

Standard I/O Text I/O Permission meaning
r O_RDONLY Open the file in read-only mode and report an error if the file does not exist.
r+ O_RDWR Open the file for reading and writing. If the file does not exist, an error will be reported.
w O_WRONLY | O_CREAT | O_TRUNC, 0664 Open the file for writing only, create it if it does not exist, or clear it if it exists
w+ O_RDWR | O_CREAT | O_TRUNC, 0664 Open the file for reading and writing. If the file does not exist, create it. If the file exists, clear it.
a O_WRONLY | O_CREAT |O_APPEND , 0664 Open the file in write-only mode, create it if it does not exist, and append it if it exists
a+ O_RDWR | O_CREAT | O_APPEND , 0664 Open the file for reading and writing. If the file does not exist, create it. If the file exists, append it.

Code example:

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

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    // 在这里可以继续处理打开的文件

    close(fd); // 关闭文件

    return 0;
}

1.2 perror, error function

perrorfunction:

#include <stdio.h>

void perror(const char *s);

#include <errno.h>

Function:

        The perror function prints the error message corresponding to the current error code to the standard error stream (stderr).

parameter:

   sis a string that can be used to customize the error message prefix.

return value:

        none

error function:

#include <errno.h>

void error(int status, int errnum, const char *format, ...);

Function:

        The error function prints an error message to the standard error stream and outputs it in the given format. It is similar to the perror function, but provides more flexibility to customize the format of the error message as needed.

parameter:

         status: Indicates the severity of the error, usually a non-zero value indicates a fatal error.

   errnum: Indicates a specific error code, which can be errnopassed as a parameter using variables.

   format: A format string, similar to the format of the printf function.

   ...: Optional additional parameter used to fill placeholders in the formatted string.

Return value: None

 Code example:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    FILE* file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        perror("Failed to open the file");
        exit(1);
    }

    // 在这里可以继续处理打开的文件

    fclose(file); // 关闭文件

    return 0;
}

1.3 close function

#include int close(int fd);

Function:

        Close an open file

parameter:

        fd: file descriptor, return value of open()

return value:

        Success: 0

        Failure: -1, and errno is set

Code example:

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

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    // 在这里可以继续处理打开的文件

    if (close(fd) == -1) {
        perror("Failed to close the file");
        exit(1);
    }

    return 0;
}

1.4 write function

#include<unistd.h>

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

Function:

        Writes the specified amount of data to file (fd).

parameter:

        fd: file descriptor

        buf: data first address

        count: length of written data (bytes)

return value:

        Success: The number of bytes actually written to the data

        Failure: -1

Code example:

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

int main() {
    int fd = open("example.txt", O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    const char* data = "Hello, World!";
    ssize_t bytes_written = write(fd, data, strlen(data));
    if (bytes_written == -1) {
        perror("Failed to write to the file");
        exit(1);
    }

    // 在这里可以继续处理打开的文件

    if (close(fd) == -1) {
        perror("Failed to close the file");
        exit(1);
    }

    return 0;
}

1.5 read function

#include<unistd.h>

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

Function:

        Read the specified amount of data into memory (buffer).

parameter:

        fd: file descriptor

        buf: first memory address

        count: number of bytes read

return value:

        Success: the number of bytes actually read

        Failure: -1

Code example:

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

#define BUFFER_SIZE 1024

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE);
    if (bytes_read == -1) {
        perror("Failed to read from the file");
        exit(1);
    }

    // 在这里可以继续处理读取的数据

    if (close(fd) == -1) {
        perror("Failed to close the file");
        exit(1);
    }

    return 0;
}

1.6 stat function

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
​int
stat(const char* path, struct stat* buf); 
int lstat(const char* pathname, struct stat * buf); 
Function: 
        Get file status information 
. The difference between stat and lstat: 
        when the file is a symbolic link, lstat returns the information of the symbolic link itself; 
        while stat returns the information of the file pointed to by the link. 
Parameters: 
        path: file name 
        buf: structure to save file information 
Return value: 
        Success: 0 
        Failure: -1

Code example:

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

int main() {
    struct stat st;
    if (stat("example.txt", &st) == -1) {
        perror("Failed to get file status");
        exit(1);
    }

    // 在这里可以继续处理文件状态信息

    return 0;
}

1.7 dup, dup2 function

dup function

#include<unistd.h>

int dup(int oldfd);

Function:

        Copy a new file descriptor through oldfd. The new file descriptor is the smallest available file descriptor in the file descriptor table of the calling process. In the end, both oldfd and the new file descriptor point to the same file.

parameter:

        oldfd: the file descriptor oldfd that needs to be copied

return value:

        Success: new file descriptor

        Failure: -1

dup2 function

#include<unistd.h>

int dup2(int oldfd, int newfd);

Function:

        Copy a new file descriptor newfd through oldfd. If successful, newfd and the function return value are the same return value. In the end, oldfd and the new file descriptor newfd point to the same file.

parameter:

        oldfd: the file descriptor that needs to be copied

        newfd: new file descriptor. This descriptor can be manually specified with a legal number (0-1023). If the specified number is already occupied (associated with a certain file), this function will automatically close the close() disconnect This number is associated with a certain file, and then this legal number is used.

return value:

        Success: return newfd

        Failure: -1

Code example:

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

int main() {
    int fd = open("example.txt", O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    // 复制文件描述符
    int new_fd = dup(fd);
    if (new_fd == -1) {
        perror("Failed to duplicate file descriptor");
        exit(1);
    }

    // 在这里可以继续处理文件描述符

    if (close(fd) == -1) {
        perror("Failed to close the file");
        exit(1);
    }

    if (close(new_fd) == -1) {
        perror("Failed to close the duplicated file");
        exit(1);
    }

    return 0;
}

1.8 fcntl function

#include<unistd.h>

#include<fcntl.h>

int fcntl(int fd, int cmd, .../* arg */);

Function:

        To change the nature of an open file, fcntl provides control over the descriptor.

parameter:

        fd: file descriptor for operation

        cmd: How to operate

        arg: For the value of cmd, fcntl can accept the third parameter int arg

return value:

        Success: returns some other value

        Failure: -1

Code example:

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

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(1);
    }

    // 获取文件状态标志
    int flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        perror("Failed to get file flags");
        exit(1);
    }

    // 在这里可以继续处理文件状态标志

    if (close(fd) == -1) {
        perror("Failed to close the file");
        exit(1);
    }

    return 0;
}

2. Other I/O functions

2.1 access function

#include<unistd.h>

int access(const char *pathname, int mode);

Function:

        Tests whether the specified file has a certain attribute.

parameter:

        pathname: file name

        mode: file permissions, 4 types of permissions

                R_OK: Whether there is read permission

                W_OK: Do you have write permission?

                X_OK: Whether there is execution permission

                F_OK: Test whether the file exists

return value:

        0: There is some permission, or the file exists

        -1: None, or the file does not exist

Code example:

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

int main() {
    if (access("example.txt", R_OK) == -1) {
        perror("Failed to access the file");
        exit(1);
    }

    // 在这里可以继续处理文件访问权限

    return 0;
}

2.2 chmod function

#include<sys/stat.h>

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

Function:

        Modify file permissions.

parameter:

        filename: file name

        mode: permission (octal number)

return value:

        Success: 0

        Failure: -1

Code example:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main() {
    if (chmod("example.txt", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
        perror("Failed to change file mode");
        exit(1);
    }

    // 在这里可以继续处理文件权限

    return 0;
}

2.3 chown function

#include<unistd.h>

int chown(const char *pathname, uid_t owner, gid_t group);

Function:

        Modify the file owner and group.

parameter:

        pathname: file or directory name

        owner: file owner id, obtained by viewing /etc/passwd

        group: The group id to which the file belongs. Get the user group id by checking /etc/passwd.

return value:

        Success: 0

        Failure: -1

Code example:

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

int main() {
    if (chown("example.txt", 1000, 1000) == -1) {
        perror("Failed to change file ownership");
        exit(1);
    }

    // 在这里可以继续处理文件所有者和所属组

    return 0;
}

2.4 truncate function

#include<unistd.h>

#include<sys/types.h>

int truncate(const char *path, off_t length);

Function:

        Modify file size.

parameter:

        path: file name

        length: specified file size

                a) Smaller than the original, delete the following part

                b) Larger than the original, expanding backwards

return value:

        Success: 0

        Failure: -1

Code example: 

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

int main() {
    if (truncate("example.txt", 100) == -1) {
        perror("Failed to truncate the file");
        exit(1);
    }

    // 在这里可以继续处理文件截断

    return 0;
}

2.5 link function

#include<unistd.h>

int link(const char *oldpath, const char *newpath);

Function:

        Create a hard link.

parameter:

        oldpath: source file name

        newpath: hard link name

return value:

        Success: 0

        Failure: -1

Code example:

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

int main() {
    if (link("example.txt", "example_link.txt") == -1) {
        perror("Failed to create hard link");
        exit(1);
    }

    // 在这里可以继续处理硬链接

    return 0;
}

2.6 symlink function

#include<unistd.h>

int symlink(const char *target, const char *linkpath);

Function:

        Create a soft link

parameter:

        target: source file name

        linkpath: soft link name

return value:

        Success: 0

        Failure: -1

Code example:

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

int main() {
    if (symlink("example.txt", "example_symlink.txt") == -1) {
        perror("Failed to create symbolic link");
        exit(1);
    }

    // 在这里可以继续处理符号链接

    return 0;
}

2.7 readlink function

#include<unistd.h>

ssize_t readlink(const char *pathname, char *buf, size_t bufsize);

Function:

        Read the file name corresponding to the soft link, not the content (this function can only read soft link files).

parameter:

        pathname: soft link name

        buf: stores the file name corresponding to the software

        bufsize: buffer size (the maximum number of bytes stored in the second parameter)

return value:

        Success: >0, read the number of characters in buf

        Failure: -1

Code example:

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

#define BUFFER_SIZE 1024

int main() {
    char buffer[BUFFER_SIZE];
    ssize_t len = readlink("example_symlink.txt", buffer, BUFFER_SIZE - 1);
    if (len == -1) {
        perror("Failed to read symbolic link");
        exit(1);
    }
    buffer[len] = '\0';

    // 在这里可以继续处理读取的符号链接目标

    return 0;
}

2.8 unlink function

#include<unistd.h>

int unlink(const char *pathname);

Function:

        Delete a file (soft and hard link files).

parameter:

        pathname: deleted file name

return value:

        Success: 0

        Failure: -1

Code example:

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

int main() {
    if (unlink("example.txt") == -1) {
        perror("Failed to remove the file");
        exit(1);
    }

    // 在这里可以继续处理文件删除

    return 0;
}

2.9 rename function

#include<stdio.h>

int rename(const char *oldpath, const char *newpath);

Function:

        Change the file name of oldpath to newpath.

parameter:

        oldpath: old file name

        newpath: new file name

return value:

        Success: 0

        Failure: -1

Code example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    if (rename("example.txt", "new_example.txt") == -1) {
        perror("Failed to rename the file");
        exit(1);
    }

    // 在这里可以继续处理文件重命名

    return 0;
}

3. Directory related functions

3.1 getcwd function

#include<unistd.h>

char *getcwd(char *buf, size_t size);

Function:

        buf: Buffer, stores the current working directory.

        size: buffer size.

return value:

        Success: Save the current process working directory location in buf

        Failure: NULL

Code example: 

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

#define PATH_MAX 4096

int main() {
    char current_path[PATH_MAX];
    if (getcwd(current_path, sizeof(current_path)) == NULL) {
        perror("Failed to get the current working directory");
        exit(1);
    }

    // 在这里可以继续处理当前工作目录

    return 0;
}

3.2 chdir function

#include<unistd.h>

int chdir(const char *path);

Function:

        Modify the path of the current process (application).

parameter:

        path: the path to switch.

return value:

        Success: 0

        Failure: -1

Code example:

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

int main() {
    if (chdir("/path/to/directory") == -1) {
        perror("Failed to change the directory");
        exit(1);
    }

    // 在这里可以继续处理目录切换

    return 0;
}

3.3 opendir function

#include<sys/types.h>

#include<dirent.h>

DIR *opendir(const char *name);

Function:

        Open a directory.

parameter:

        name: directory name.

return value:

        Success: Returns a pointer to the directory structure.

        Failure: NULL

Code example:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main() {
    DIR* dir = opendir(".");
    if (dir == NULL) {
        perror("Failed to open the directory");
        exit(1);
    }

    // 在这里可以继续处理打开的目录

    closedir(dir); // 关闭目录

    return 0;
}

3.4 closedir function

#include<sys/types.h>

#include<dirent.h>

int closedir(DIR *dirp);

Function:

        Close the directory.

parameter:

        dirp: the pointer returned by opendir.

return value:

        Success: 0

        Failure: -1

 Code example:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main() {
    DIR* dir = opendir(".");
    if (dir == NULL) {
        perror("Failed to open the directory");
        exit(1);
    }

    // 在这里可以继续处理打开的目录

    if (closedir(dir) == -1) {
        perror("Failed to close the directory");
        exit(1);
    }

    return 0;
}

3.5 readdir function

#include<dirent.h>

struct dirent *readdir(DIR *dirp);

Function:

        dirp: the return value of opendir.

return value:

        Success: Directory structure pointer.

        Failure: NULL

Code example: 

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main() {
    DIR* dir = opendir(".");
    if (dir == NULL) {
        perror("Failed to open the directory");
        exit(1);
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL) {
        // 在这里可以处理每个目录项
    }

    closedir(dir); // 关闭目录

    return 0;
}

Summarize:

        This blog covers the use of commonly used system call functions, including system call functions in different fields such as process control, file system control, system control, memory management, network management, Socket control, and user management. We introduced the functions, parameters, and return values ​​of each system call function, and provided corresponding C language code examples.

        I hope you found this blog helpful, and if you have any questions or need further assistance, please feel free to ask. Thanks!

   

Guess you like

Origin blog.csdn.net/crr411422/article/details/131527068