C语言与操作系统交互探秘

系统调用与库函数 在 C语言中,系统调用是用户程序与操作系统内核交互的桥梁。以下是常见系统调用的概述:

文件操作类:open()、read()、write()、close()、lseek() 进程控制类:fork()、exec()、wait()、exit() 信号处理类:signal()、kill() 进程间通信:pipe()、shmget()、msgget() 网络通信:socket()、bind()、listen()、accept() 系统调用 vs 库函数:

系统调用是操作系统提供的接口,进入内核态执行 库函数是对系统调用的封装(如 fread 封装了 read) 系统调用开销大但能访问底层资源,库函数效率高且跨平台 工作原理:

用户程序通过特定指令(如 int 0x80 或 syscall)触发系统调用 CPU 切换到内核态执行对应的内核服务例程 内核处理请求并返回结果 CPU 切回用户态继续执行 以下是一个简单的系统调用示例:


arduino

体验AI代码助手

代码解读

复制代码

#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { int fd; char buffer[20] = "Hello, World!\n"; // 系统调用:打开文件 fd = open("test.txt", O_WRONLY | O_CREAT, 0644); if (fd == -1) { perror("open failed"); return 1; } // 系统调用:写入文件 write(fd, buffer, 14); // 系统调用:关闭文件 close(fd); return 0; }

文件操作与 I/O 系统 C语言提供了两套文件操作接口:

标准 I/O 库:fopen()、fread()、fwrite()、fclose() 等 系统调用:open()、read()、write()、close() 等 标准 I/O 与系统调用的关系:

标准 I/O 基于系统调用实现,提供缓冲机制 系统调用直接操作文件描述符,无缓冲 文件系统基础:

inode:存储文件元数据(权限、所有者、时间戳等) 目录结构:目录文件存储文件名到 inode 的映射 文件描述符表:每个进程维护一个打开文件的描述符表 I/O 模型:

阻塞 I/O:操作直到完成才返回 非阻塞 I/O:立即返回,需轮询结果 I/O 多路复用:通过 select/poll/epoll 同时监控多个文件描述符 异步 I/O:操作完成后通过回调通知 以下是一个使用 select 实现的 I/O 多路复用示例:


arduino

体验AI代码助手

代码解读

复制代码

#include <stdio.h> #include <stdlib.h> #include <sys/select.h> #include <unistd.h> int main() { fd_set readfds; struct timeval timeout; int fd_stdin = fileno(stdin); char buffer[100]; while (1) { // 清空文件描述符集 FD_ZERO(&readfds); // 添加标准输入到监控集 FD_SET(fd_stdin, &readfds); // 设置超时时间 timeout.tv_sec = 5; timeout.tv_usec = 0; // 调用 select 监控 int result = select(fd_stdin + 1, &readfds, NULL, NULL, &timeout); https://www.fglt.me/ if (result < 0) { perror("select failed"); exit(EXIT_FAILURE); } else if (result == 0) { printf("Timeout occurred!\n"); } else { // 标准输入就绪,读取数据 if (FD_ISSET(fd_stdin, &readfds)) { fgets(buffer, sizeof(buffer), stdin); printf("Read: %s", buffer); } } } return 0; }

信号处理机制 信号基本概念:

信号是软件中断,用于通知进程发生了异步事件 常见信号:SIGINT(2)、SIGTERM(15)、SIGKILL(9)、SIGSEGV(11) 信号处理方式:

默认处理:执行系统预设动作(如终止进程) 忽略信号:不做任何处理 捕获信号:注册信号处理函数 信号处理函数注意事项:

只能调用异步信号安全的函数 避免执行复杂操作 使用 volatile sig_atomic_t 变量进行进程间通信 以下是一个信号处理的示例:


arduino

体验AI代码助手

代码解读

复制代码

#include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> volatile sig_atomic_t flag = 0; // 信号处理函数 void sigint_handler(int signum) { if (signum == SIGINT) { printf("\nCaught SIGINT, setting flag...\n"); flag = 1; } } int main() { // 注册信号处理函数 if (signal(SIGINT, sigint_handler) == SIG_ERR) { perror("signal registration failed"); return 1; } printf("Running... Press Ctrl+C to exit.\n"); // 主循环 while (!flag) { printf("Working...\n"); sleep(1); } printf("Exiting gracefully...\n"); return 0; }

信号在进程间通信中的应用:

使用 kill() 函数向指定进程发送信号 使用 sigqueue() 可以传递附加数据 信号是一种简单但有限的进程间通信方式

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值