系统调用与库函数
在 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 切回用户态继续执行
以下是一个简单的系统调用示例:
文件操作与 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 多路复用示例:
信号处理机制
信号基本概念:
- 信号是软件中断,用于通知进程发生了异步事件
- 常见信号:SIGINT(2)、SIGTERM(15)、SIGKILL(9)、SIGSEGV(11)
信号处理方式:
- 默认处理:执行系统预设动作(如终止进程)
- 忽略信号:不做任何处理
- 捕获信号:注册信号处理函数
信号处理函数注意事项:
- 只能调用异步信号安全的函数
- 避免执行复杂操作
- 使用 volatile sig_atomic_t 变量进行进程间通信
以下是一个信号处理的示例:
信号在进程间通信中的应用:
- 使用
kill()
函数向指定进程发送信号 - 使用
sigqueue()
可以传递附加数据 - 信号是一种简单但有限的进程间通信方式