c,#include,,// 定义一个名为 myFunction 的函数,它接受两个整数参数并返回它们的和,int myFunction(int a, int b) {, return a + b;,},,int main() {, int result = myFunction(3, 4); // 调用函数并传递参数, printf("The result is: %d,", result); // 输出结果, return 0;,},
``,,这段代码展示了如何在 Linux 系统中使用 C 语言编写一个简单的函数来计算两个数的和,并在主函数中调用它。在Linux操作系统中,func
是一个非常重要的概念,它指的是系统调用的函数,这些函数是操作系统提供给应用程序的接口,用于执行各种操作,如文件I/O、进程管理、网络通信等,本文将详细介绍Linux中的系统调用函数,包括它们的分类、使用方法以及一些常见的系统调用函数示例。
系统调用函数的分类
在Linux中,系统调用函数可以分为以下几类:
1、文件操作相关函数:如open、close、read、write等,用于对文件进行打开、关闭、读取和写入操作。
2、进程控制相关函数:如fork、exec、wait等,用于创建新进程、执行程序和等待子进程结束。
3、进程间通信相关函数:如pipe、socketpair、shmget等,用于实现进程间的通信。
4、内存管理相关函数:如malloc、free、brk等,用于动态分配和释放内存。
5、设备控制相关函数:如ioctl、fcntl等,用于控制设备的输入输出操作。
6、网络编程相关函数:如socket、bind、listen等,用于实现网络编程。
7、时间管理相关函数:如time、sleep等,用于获取当前时间和使程序暂停一段时间。
8、用户信息相关函数:如getuid、setuid等,用于获取和设置用户的ID。
9、组信息相关函数:如getgid、setgid等,用于获取和设置组的ID。
10、权限管理相关函数:如chmod、chown等,用于修改文件或目录的权限和所有者。
11、信号处理相关函数:如signal、kill等,用于处理信号。
系统调用函数的使用方法
在Linux中,系统调用函数通常以C语言的形式提供给用户使用,用户可以通过包含相应的头文件(如#include <sys/types.h>、#include <unistd.h>等)来使用这些函数,下面以几个常见的系统调用函数为例,介绍它们的使用方法。
1、open函数:用于打开一个文件,原型为int open(const char *pathname, int flags);其中pathname是要打开的文件路径,flags是打开文件的标志(如只读、只写等),int fd = open("example.txt", O_RDONLY);//以只读方式打开example.txt文件。
2、close函数:用于关闭一个文件,原型为int close(int fd);其中fd是文件描述符,close(fd);//关闭文件描述符为fd的文件。
3、read函数:用于从文件中读取数据,原型为ssize_t read(int fd, void *buf, size_t count);其中fd是文件描述符,buf是存储读取数据的缓冲区,count是要读取的数据大小,char buffer[100];read(fd, buffer, sizeof(buffer));//从文件描述符为fd的文件中读取最多100个字节的数据到buffer中。
4、write函数:用于向文件中写入数据,原型为ssize_t write(int fd, const void *buf, size_t count);其中fd是文件描述符,buf是要写入的数据缓冲区,count是要写入的数据大小,const char *data = "Hello, world!";write(fd, data, strlen(data));//将字符串"Hello, world!"写入到文件描述符为fd的文件中。
5、fork函数:用于创建一个新进程,原型为pid_t fork(void);如果成功,返回两次:一次是在父进程中返回子进程的PID;另一次是在子进程中返回0,如果失败,返回-1,pid_t pid = fork();if (pid == 0) { //子进程代码 } else if (pid > 0) { //父进程代码 } else { //fork失败 }
6、exec函数族:用于执行一个新程序,有多个版本,如execl、execp、execle等,原型分别为int execl(const char *path, const char *arg, ...);int execp(const char *file, char *const argv[]);int execle(const char *path, const char *arg, ..., char *const envp[]);char *args[] = {"/bin/ls", "-l", "/home/user", NULL};execvp(args[0], args);//执行/bin/ls -l /home/user命令
7、wait函数:用于等待一个子进程结束,原型为pid_t wait(int *status);如果成功,返回子进程的PID;如果失败,返回-1,int status;wait(&status);//等待任意一个子进程结束并获取其状态码
8、pipe函数:用于创建一个管道,原型为int pipe(int fd[2]);如果成功,返回0;如果失败,返回-1,int fds[2];pipe(fds);//创建一个管道,fds[0]是读端文件描述符,fds[1]是写端文件描述符
9、socketpair函数:用于创建一个双向管道,原型为int socketpair(int domain, int type, int protocol, int sv[2]);如果成功,返回0;如果失败,返回-1,int sv[2];socketpair(AF_UNIX, SOCK_STREAM, 0, sv);//创建一个双向管道,sv[0]和sv[1]分别是两个端点的文件描述符
10、shmget函数:用于获取共享内存段的标识符,原型为int shmget(key_t key, size_t size, int shmflg);如果成功,返回共享内存段的标识符;如果失败,返回-1,key_t key = ftok("shmfile", 'R');int shmid = shmget(key, 1024, 0666|IPC_CREAT);//创建一个大小为1024字节的共享内存段,并将其标识符存储在shmid中
11、malloc函数:用于动态分配内存,原型为void *malloc(size_t size);如果成功,返回指向分配的内存块的指针;如果失败,返回NULL,char *str = (char *)malloc(100 * sizeof(char));//分配一个大小为100个字符的内存块给str指针
12、free函数:用于释放之前通过malloc分配的内存,原型为void free(void *ptr);其中ptr是要释放的内存块的指针,free(str);//释放str指针所指向的内存块
常见系统调用函数示例
以下是一些常见的系统调用函数的使用示例:
1、使用open、read和write函数实现一个简单的文本编辑器:``c #include <fcntl.h> #include <unistd.h> #include <stdio.h> #define BUFFER_SIZE 1024 int main() { int fd = open("example.txt", O_RDWR | O_CREAT, 0644); if (fd == -1) { perror("open"); return 1; } char buffer[BUFFER_SIZE]; while (1) { printf("请输入要写入的内容:"); fgets(buffer, BUFFER_SIZE, stdin); if (strncmp(buffer, "exit", 4) == 0) break; int len = strlen(buffer); if (write(fd, buffer, len) != len) { perror("write"); close(fd); return 1; } } close(fd); return 0; }
``
2、使用fork和exec函数实现一个简单的Shell:```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #define MAX_INPUT_SIZE 1024 int main() { char input[MAX_INPUT_SIZE]; while (1) { printf("请输入命令:"); fgets(input, MAX_INPUT_SIZE, stdin); if (strncmp(input, "exit
", 5) == 0) break; int pid = fork(); if (pid == 0) { //子进程代码 system(input); exit(0); } else if (pid > 0) { //父进程代码 wait(NULL); } else { perror("fork"); return 1; } } return 0; } ```
3、使用pipe和dup2函数实现一个简单的管道通信程序:``c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define BUFFER_SIZE 1024 int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) { //子进程代码 close(pipefd[0]); //关闭读端 dup2(pipefd[1], STDOUT_FILENO); //将标准输出重定向到管道的写端 close(pipefd[1]); //关闭写端 execlp("ls", "ls", NULL); //执行ls命令 } else { //父进程代码 close(pipefd[1]); //关闭写端 char buffer[BUFFER_SIZE]; int nbytes = read(pipefd[0], buffer, BUFFER_SIZE); close(pipefd[0]); //关闭读端 printf("子进程输出:%s", buffer); } return EXIT_SUCCESS; }
``
4、使用socketpair和fork函数实现一个简单的父子进程通信程序:```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #define PAIR_SOCKET int pair_socket[2]; if (socketpair(AF_UNIX, SOCK_STREAM, PAIR_SOCKET) == -1) { perror("socketpair"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) { //子进程代码 close(PAIR_SOCKET[0]); //关闭读端 char message[] = "Hello from child"; write(PAIR_SOCKET[1], message, sizeof(message)); close(PAIR_SOCKET[1]); //关闭写端 } else { //父进程代码 close(PAIR_SOCKET[1]); //关闭写端 char buffer[1024]; read(PAIR_SOCKET[0], buffer, sizeof(buffer)); printf("收到来自子进程的消息:%s
", buffer); close(PAIR_SOCKET[0]); //关闭读端 } return EXIT_SUCCESS; } ```
5、使用shmget和shmat函数实现一个简单的共享内存通信程序:```c #include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #define SHM_KEY 1234 key_t key = SHM_KEY; int shmid = shmget(key, 1024, 0666|IPC_CREAT); if (shmid == -1) { perror("shmget"); exit(EXIT_FAILURE); } void *shmaddr = shmat(shmid, NULL, 0); if (shmaddr == (void *)-1) { perror("shmat"); exit(EXIT_FAILURE); } strcpy((char *)shmaddr, "Hello from parent process"); //向共享内存中写入数据 sleep(2); //等待子进程读取数据 shmdt(shmaddr); //分离共享内存地址空间 return 0; } int main() { key_t key = SHM_KEY; int shmid = shmget(key, 1024, 0666|IPC_CREAT); if (shmid == -1) { perror("shmget"); exit(EXIT_FAILURE); } void *shmaddr = shmat(shmid, NULL, 0); if (shmaddr == (void *)-1) { perror("shmat"); exit(EXIT_FAILURE); } printf("收到来自父进程的消息:%s
", (char *)shmaddr); shmdt(shmaddr); //分离共享内存地址空间 return 0; } ```
6、使用malloc和free函数实现一个简单的动态内存分配和释放程序:``c #include <stdio.h> #include <stdlib.h> #include <string.h> #define ARRAY_SIZE 10 int main() { int *array = (int *)malloc(ARRAY_SIZE * sizeof(int)); if (array == NULL) { perror("malloc"); return 1; } for (int i = 0; i < ARRAY_SIZE; i++) { array[i] = i; } for (int i = 0; i < ARRAY_SIZE; i++) { printf("%d ", array[i]); } free(array); //释放动态分配的内存 return 0; }
``
7、使用time和alarm函数实现一个简单的定时器程序:```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <time.h> #define TIMEOUT 5 void timer_handler(int signum) { printf("定时器超时!
"); exit(0); } int main() { signal(SIGALRM, timer_handler); alarm(TIMEOUT); //设置定时器时间为5秒 while (1) { printf("等待定时器超时...
"); sleep(1); } return 0; } ```
8、使用getpid和kill函数实现一个简单的进程控制程序:```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #define PID 1234 int main() { int result = kill(PID, SIGKILL); if (result == 0) { printf("成功杀死进程号为%d的进程
", PID); } else { perror("kill"); } return 0; } ```
9、使用getppid和setpgid函数实现一个简单的进程组控制程序:``c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #define CHILDREN_NUM 3 int main() { pid_t pids[CHILDREN_NUM]; for (int i = 0; i < CHILDREN_NUM; i++) { pids[i] = fork(); if (pids[i] == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (pids[i] == 0) { //子进程代码 setpgid(0, pids[i]); //设置子进程为新的进程组组长 while (1) { pause(); //等待信号 } } } for (int i = 0; i < CHILDREN_NUM; i++) { waitpid(pids[i], NULL, WNOHANG); } return 0; }
``
10、使用setuid和setgid函数实现一个简单的权限管理程序:```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define UID 1000 #define GID 1000 int main() { if (setuid(UID) == -1) { perror("setuid"); exit(EXIT_FAILURE); } if (setuid(GID) == -1) { perror("setuid"); exit(EXIT_FAILURE); } printf("当前用户ID: %d
", getuid()); printf("当前组ID: %d
", getgid()); return 0; } ```
FAQs
Q1:什么是系统调用?
A1:系统调用(System Call)是指操作系统提供的一组API,用于在用户空间与内核空间之间进行交互,它们允许用户程序请求操作系统执行特定的服务,如文件操作、进程管理、网络通信等,系统调用是计算机系统中不可或缺的一部分,因为它们提供了一种安全、可靠的方式来访问底层硬件资源和操作系统功能。
Q2:如何使用fork()函数创建新进程?
A2:使用fork()函数创建新进程的方法如下:
1、调用fork()函数,如果fork()成功,它会返回两次:一次在父进程中返回子进程的PID,一次在子进程中返回0,如果fork()失败,则返回-1。
2、根据fork()的返回值判断当前是父进程还是子进程,如果是父进程,则可以继续执行后续代码;如果是子进程,则可以执行其他任务或退出。
3、如果需要,可以使用exec()系列函数替换子进程的映像,使其执行新的程序。
4、如果不需要替换子进程映像,则可以直接在子进程中执行所需任务。
5、如果需要在父进程中等待子进程结束,可以使用wait()或waitpid()函数。
6、如果需要在父进程中获取子进程的状态码,可以使用wait()或waitpid()函数的返回值。
Q3:如何使用pipe()函数实现父子进程间通信?
A3:使用pipe()函数实现父子进程间通信的方法如下:
1、调用pipe()函数创建一个管道,该函数会返回一个整型数组,其中pipefd[0]表示读端文件描述符,pipefd[1]表示写端文件描述符。
2、在父进程中关闭写端文件描述符(pipefd[1]),只保留读端文件描述符(pipefd[0]),这样父进程就可以从管道中读取数据了。
3、在子进程中关闭读端文件描述符(pipefd[0]),只保留写端文件描述符(pipefd[1]),这样子进程就可以向管道中写入数据了。
4、在子进程中执行所需任务后,将结果写入管道,可以使用write()函数将数据写入管道。
5、在父进程中等待子进程结束(可以使用wait()或waitpid()函数),然后从管道中读取子进程写入的数据,可以使用read()函数从管道中读取数据。
6、如果需要,可以在父进程中关闭读端文件描述符(pipefd[0]),以释放资源。
小伙伴们,上文介绍了“func linux”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。