【系统调用】常用系统调用函数:详细介绍

目录

0. 系统调用概念

1. 常用系统调用函数 

1.1 open函数

1.2 perror、error函数

1.3 close函数

1.4 write函数

1.5 read函数

1.6 stat函数

1.7 dup、dup2函数

1.8 fcntl函数

2. 其他I/O函数

2.1 access函数

2.2 chmod函数

2.3 chown函数

2.4 truncate函数

2.5 link函数

2.6 symlink函数

2.7 readlink函数

2.8 unlink函数

2.9 rename函数

3. 目录相关函数

3.1 getcwd函数

3.2 chdir函数

3.3 opendir函数

3.4 closedir函数

3.5 readdir函数

总结:


0. 系统调用概念

操作系统的职责

        操作系统用来管理所有的资源,并将不同的设备和不同的程序关联起来。

什么是Linux系统编程

        在有操作系统的环境下编程,并使用操作系统提供的系统调用及各种库,对系统资源进行访问。

系统编程主要就是为了让用户能够更好和更方便的操作硬件设备,并且对硬件设备也起到保护作用。我们所写的程序,本质就是对硬件设备的操作,所以操作系统提供接口可以对硬件进行操作。

系统调用概述:

        本质都是要对硬件设备进行操作,但是Linux操作系统在硬件之上设置了内核,也就是只有内核才可以直接操作硬件设备,如果想操作内核,需要调用内核的系统调用,如果要操作内核中的系统调用,有三种方式:

  • 第一种:shell,用户通过shell命令,由shell解释器操作内核的系统调用。
  • 第二种:库函数,用户通过应用层库函数的接口,比如fread对内核的系统调用进行操作。
  • 第三种:应用层系统调用,它可以直接对内核的系统调用进行操作。

系统调用时操作系统提供给用户程序的一组“特殊”的函数接口。

Linux的不同版本提供了两三百个系统调用。

用户程序可以通过这组接口获得操作系统(内核)提供的服务。

 系统调用按照功能逻辑大致可分为:

        进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控制、用户管理。

系统调用的返回值:

        通常,用一个非负的返回值来表明错误,返回一个0值表明成功。

        错误信息存放在全局变量errno中,用户可用perror函数打印出错信息。

系统调用遵循的规范:

        在Linux中,应用程序编程接口(API)遵循POSIX标准。

系统调用I/O函数

文件描述符:

        文件描述符是非负整数。打开现存文件或新建文件时,系统(内核)会返回一个文件描述符。文件描述符用来指定已打凯的文件。

        在系统调用(文件IO)中,文件描述符对文件起到标识作用,如果要操作文件,就是对文件描述符的操作。

当一个程序运行或一个进程开启时,系统会自动创建三个文件描述符。

  • #define STDIN_FILENO      0  //标准输入的文件描述符
  • #define STDOUT_FILENO  1  //标准输出的文件描述符
  • #define STDERR_FILENO  2  //标准错误的文件描述符

如果自己打开文件,会返回文件描述符,而文件描述符一般按照从小到大依次创建的顺序。

1. 常用系统调用函数 

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

功能:

        代开文件,如果文件不存在则可以选择创建。

参数:

        pathname:文件的路径及文件名。

        flags:打开文件的行为标志,必选项 O_RDONLY, O_WRONLY, O_RDWR

        mode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的权限。

返回值:

        成功:文件描述符

        失败:-1

flags详细说明

必选项:

取值含义
O_RDONLY以只读的方式打开
O_WRONLY以只写的方式打开
O_RDWR以可读、可写的方式打开

可选项:

取值含义
O_CREAT文件不存在则创建文件,必须跟mode(一般0664)
O_EXCL如果同时指定了O_CREAT,且文件已经存在,则出错
O_TRUNC如果文件存在,则清空文件内容
O_APPEND写文件时,数据添加到文件末尾
O_NONBLOCK

对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O

mode补充说明:

1) 文件最终权限:mode & ~umask

2) shell进程的umask掩码可以用umask命令查看

umask:查看掩码(补码)

umask mode:设置掩码,mode为八进制数

umask -S:查看各组用户的默认操作权限

文件I/O和标准I/O权限对比:

标准I/O文件I/O权限含义
rO_RDONLY以只读的方式打开文件,如果文件不存在则报错
r+O_RDWR以读写的方式打开文件,如果文件不存在则报错
wO_WRONLY | O_CREAT | O_TRUNC, 0664以只写的方式打开文件,如果文件不存在则创建,如果文件存在则清空
w+O_RDWR | O_CREAT | O_TRUNC, 0664以读写的方式打开文件,如果文件不存在则创建,如果文件存在则清空
aO_WRONLY | O_CREAT |O_APPEND , 0664以只写的方式打开文件,如果文件不存在则创建,如果文件存在则追加
a+O_RDWR | O_CREAT | O_APPEND , 0664以读写的方式打开文件,如果文件不存在则创建,如果文件存在则追加

代码示例:

#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函数

perror函数:

#include <stdio.h>

void perror(const char *s);

#include <errno.h>

功能:

        perror函数根据当前的错误代码,将与该错误代码对应的错误消息打印到标准错误流(stderr)中。

参数:

   s是一个字符串,可用于自定义错误消息前缀。

返回值:

        无

error函数:

#include <errno.h>

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

功能:

        error函数将错误消息打印到标准错误流,并以给定的格式输出。它与perror函数相似,但提供了更多的灵活性,可以根据需要自定义错误消息的格式。

参数:

         status:表示错误的严重程度,通常为非零值表示致命错误。

   errnum:表示具体的错误代码,可以使用errno变量作为参数传递。

   format:一个格式化字符串,类似于printf函数的格式。

   ...:可选的附加参数,用于填充格式化字符串中的占位符。

返回值:无

 代码示例:

#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函数

#include int close(int fd);

功能:

        关闭已打开的文件

参数:

        fd : 文件描述符,open()的返回值

返回值:

        成功:0

        失败: -1, 并设置errno

代码示例:

#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函数

#include<unistd.h>

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

功能:

        把指定数目的数据写到文件(fd)。

参数:

        fd:文件描述符

        buf:数据首地址

        count:写入数据的长度(字节)

返回值:

        成功:实际写入数据的字节个数

        失败:-1

代码示例:

#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函数

#include<unistd.h>

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

功能:

        把指定数目的数据读到内存(缓冲区)。

参数:

        fd:文件描述符

        buf:内存首地址

        count:读取的字节个数

返回值:

        成功:实际读取到的字节个数

        失败:-1

代码示例:

#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函数

#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);
功能:
        获取文件状态信息
stat和lstat的区别:
        当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;
        而stat返回的是该链接指向的文件的信息。
参数:
        path:文件名
        buf:保存文件信息的结构体
返回值:
        成功: 0
        失败: -1

代码示例:

#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函数

dup函数

#include<unistd.h>

int dup(int oldfd);

功能:

        通过oldfd复制出一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终oldfd和新的文件描述符都指向同一个文件。

参数:

        oldfd:需要复制的文件描述符oldfd

返回值:

        成功:新的文件描述符

        失败:-1

dup2函数

#include<unistd.h>

int dup2(int oldfd, int newfd);

功能:

        通过oldfd复制出一个新的文件描述符newfd,如果成功,newfd和函数返回值是同一个返回值,最终oldfd和新的文件描述符newfd都指向同一个文件。

参数:

        oldfd:需要复制的文件描述符

        newfd:新的文件描述符,这个描述符可以人为指定一个合法的数字(0-1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭close()断开这个数字和某个文件的关联,再来使用这个合法数字。

返回值:

        成功:返回newfd

        失败:-1

代码示例:

#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函数

#include<unistd.h>

#include<fcntl.h>

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

功能:

        改变已打开的文件性质,fcntl针对描述符提供控制。

参数:

        fd:操作的文件描述符

        cmd:操作方法

        arg:针对cmd的值,fcntl能够接受第三个参数int arg

返回值:

        成功:返回某个其他值

        失败:-1

代码示例:

#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. 其他I/O函数

2.1 access函数

#include<unistd.h>

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

功能:

        测试指定文件是否具有某种属性。

参数:

        pathname:文件名

        mode:文件权限,4种权限

                R_OK:是否有读权限

                W_OK:是否有写权限

                X_OK:是否有执行权限

                F_OK:测试文件是否存在

返回值:

        0:有某种权限,或者文件存在

        -1:没有,或文件不存在

代码示例:

#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函数

#include<sys/stat.h>

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

功能:

        修改文件权限。

参数:

        filename:文件名

        mode:权限(8进制数)

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<unistd.h>

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

功能:

        修改文件所有者和所属组。

参数:

        pathname:文件或目录名

        owner:文件所有者id,通过查看/etc/passwd所得到所有者id

        group:文件所属组id,通过查看/etc/passwd得到用户组id

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<unistd.h>

#include<sys/types.h>

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

功能:

        修改文件大小。

参数:

        path:文件名字

        length:指定的文件大小

                a)比原来小,删掉后边的部分

                b)比原来大,向后拓展

返回值:

        成功:0

        失败:-1

代码示例: 

#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函数

#include<unistd.h>

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

功能:

        创建一个硬链接。

参数:

        oldpath:源文件名字

        newpath:硬链接名字

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<unistd.h>

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

功能:

        创建一个软连接

参数:

        target:源文件名字

        linkpath:软连接名字

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<unistd.h>

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

功能:

        读软连接对应的文件名,不是读内容(该函数只能读软连接文件)。

参数:

        pathname:软连接名

        buf:存放软件对应的文件名

        bufsize:缓冲区大小(第二个参数存放的最大字节数)

返回值:

        成功:>0,读到buf中的字符个数

        失败:-1

代码示例:

#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函数

#include<unistd.h>

int unlink(const char *pathname);

功能:

        删除一个文件(软硬链接文件)。

参数:

        pathname:删除的文件名字

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<stdio.h>

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

功能:

        把oldpath的文件名改为newpath。

参数:

        oldpath:旧文件名

        newpath:新文件名

返回值:

        成功:0

        失败:-1

代码示例:

#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. 目录相关函数

3.1 getcwd函数

#include<unistd.h>

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

功能:

        buf:缓冲区,存储当前的工作目录。

        size:缓冲区大小。

返回值:

        成功:buf中保存当前进程工作目录位置

        失败:NULL

代码示例: 

#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函数

#include<unistd.h>

int chdir(const char *path);

功能:

        修改当前进程(应用程序)的路径。

参数:

        path:切换的路径。

返回值:

        成功:0

        失败:-1

代码示例:

#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函数

#include<sys/types.h>

#include<dirent.h>

DIR *opendir(const char *name);

功能:

        打开一个目录。

参数:

        name:目录名。

返回值:

        成功:返回指向该目录结构体指针。

        失败:NULL

代码示例:

#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函数

#include<sys/types.h>

#include<dirent.h>

int closedir(DIR *dirp);

功能:

        关闭目录。

参数:

        dirp:opendir返回的指针。

返回值:

        成功:0

        失败:-1

 代码示例:

#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函数

#include<dirent.h>

struct dirent *readdir(DIR *dirp);

功能:

        dirp:opendir的返回值。

返回值:

        成功:目录结构体指针。

        失败:NULL

代码示例: 

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

总结:

        本篇博客涵盖了常用系统调用函数的使用介绍,涉及了进程控制、文件系统控制、系统控制、内存管理、网络管理、Socket控制、用户管理等不同领域的系统调用函数。我们介绍了每个系统调用函数的功能、参数、返回值,并提供了相应的C语言代码示例。

        希望本篇博客对您有所帮助,如果还有任何问题或需要进一步的帮助,请随时提问。谢谢!

   

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 SQL Server 中,有许多常用系统函数可以帮助我们进行数据处理和计算,以下是一些常用系统函数及其调用方式: 1.字符串函数 LEN():返回字符串的长度,语法如下: SELECT LEN('Hello World'); -- 输出 11 SUBSTRING():返回指定位置的子字符串,语法如下: SELECT SUBSTRING('Hello World', 1, 5); -- 输出 Hello LOWER():将字符串转换为小写字母,语法如下: SELECT LOWER('Hello World'); -- 输出 hello world UPPER():将字符串转换为大写字母,语法如下: SELECT UPPER('Hello World'); -- 输出 HELLO WORLD 2.数值函数 SUM():计算列中所有数值的总和,语法如下: SELECT SUM(column_name) FROM table_name; AVG():计算列中所有数值的平均值,语法如下: SELECT AVG(column_name) FROM table_name; MAX():计算列中所有数值的最大值,语法如下: SELECT MAX(column_name) FROM table_name; MIN():计算列中所有数值的最小值,语法如下: SELECT MIN(column_name) FROM table_name; 3.日期函数 GETDATE():返回当前日期和时间,语法如下: SELECT GETDATE(); -- 输出当前日期和时间 DATEPART():返回日期中的指定部分,语法如下: SELECT DATEPART(year, '2022-01-01'); -- 输出 2022 DATEDIFF():返回两个日期之间的差异,语法如下: SELECT DATEDIFF(day, '2022-01-01', '2022-01-05'); -- 输出 4 4.类型转换函数 CAST():将一个数据类型转换为另一个数据类型,语法如下: SELECT CAST(column_name AS new_data_type) FROM table_name; CONVERT():将一个数据类型转换为另一个数据类型,语法如下: SELECT CONVERT(new_data_type, column_name) FROM table_name; 以上是 SQL Server 中常用系统函数及其调用方式,可以根据需要灵活运用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SecureCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值