目录
进程控制(Process Control)
在操作系统中,程序是通过“进程(process)”来运行的。进程控制类系统调用用于创建、执行、终止进程,以及控制进程的运行、同步和资源分配。
这些系统调用是操作系统中最核心的一类,它们决定了程序如何启动、运行、暂停、终止,以及进程之间如何交互。
常见的进程控制 系统调用及作用:
系统调用功能 | 示例说明 |
---|---|
end / abort | 结束当前进程:exit() 、abort() |
load / execute | 加载并运行新程序:exec() 、system() |
create process / terminate process | 创建子进程:fork() 、终止:exit() 、kill() |
get / set process attributes | 获取或修改进程的属性,如 PID、优先级等:getpid() 、setpriority() |
wait for time | 睡眠一定时间:sleep() 、usleep() 、nanosleep() |
wait event / signal event | 进程同步:wait() , signal() , waitpid() |
allocate / free memory | 动态内存管理:malloc() (用户库函数),底层可能涉及系统调用如 brk() 或 mmap() |
1️⃣ end
/ abort
— 结束或强制中止程序
end
:程序正常执行完,调用exit()
,告诉系统“我已经完成了,可以清理资源了”。abort
:程序出现严重错误时,调用abort()
强行终止执行。
类比:就像你写作业写完了说“我写完了”是 end()
,作业突然丢了、无法继续写是 abort()
。
2️⃣ load
/ execute
— 加载并执行新程序
load
:操作系统把一个程序从磁盘加载进内存execute
:让 CPU 执行这个程序
举例:你双击“写字板”,操作系统就:
把写字板程序从硬盘“load”到内存;
然后“execute”,即执行它。
Linux 中用 exec()
函数完成这一步。比如:exec("gedit")
→ 执行文本编辑器。
3️⃣ create process
/ terminate process
— 创建或终止进程
创建进程的系统调用是:
fork()
(拷贝一个新进程)终止进程用:
exit()
,或者给其他进程发送kill()
类比:妈妈(父进程)生了个小孩(子进程) = fork()
小孩长大离家或死去 = exit()
4️⃣ get process attributes
/ set process attributes
(获取或设置进程属性)
比如查看进程号(
getpid()
)、父进程号(getppid()
)、设置优先级(setpriority()
)
类比:每个员工都有编号(PID)、领导编号(PPID)、权限等级(优先级)
5️⃣ wait for time
— 等待一段时间
用
sleep(5)
就可以暂停进程 5 秒钟
像你写完一段代码,想等几秒看看结果 → 就用 sleep()
6️⃣ wait event
/ signal event
— 等待或通知其他进程
wait()
:父进程等待子进程完成signal()
/kill()
:给其他进程发消息(通知或终止)
类比:爸爸等儿子写完作业才带他出去玩(wait()
),儿子喊“我写完了!”(signal()
)
7️⃣ allocate memory
/ free memory
— 动态申请或释放内存
程序运行中如果需要临时使用内存,就调用内存分配函数
例如
malloc()
虽然是库函数,但背后可能调用系统调用brk()
或mmap()
类比:你写作业突然需要一个新笔记本 → 向操作系统申请一本(内存)
小例子:一个小程序可能会这么运行:
int main() {
int pid = fork(); // 创建一个子进程
if (pid == 0) {
exec("gedit"); // 子进程打开文本编辑器
} else {
wait(); // 父进程等待子进程完成
}
exit(0); // 正常结束
}
文件操作(File Manipulation)
文件操作类是指程序在运行中,通过“系统调用”来请求操作系统对文件进行创建、读写、删除、信息获取等管理操作。
就像你在使用“记事本”打开 .txt
文件并保存内容时,实际上背后操作系统在帮你执行一系列文件系统调用。
为什么需要“系统调用”来操作文件?
程序是不能直接碰硬盘的。
比如你写了一个程序,它想保存一篇日记,它必须向操作系统申请:“请帮我打开/创建一个文件,我要写进去内容!”
这个“申请”的过程,就是通过 系统调用(System Call)完成的。
常见的文件操作系统调用
🔹 1. 创建文件(Create File)
open("mydiary.txt", O_CREAT);
操作系统帮你在磁盘上创建一个空文件
你说:“操作系统,请给我一本新日记本”,操作系统就新建一个
mydiary.txt
文件。
🔹 2. 打开文件(Open)
int fd = open("mydiary.txt", O_RDWR);
打开文件后,系统会返回一个数字(叫文件描述符 fd)
程序就可以通过这个 fd 来对文件进行后续操作
🔹 3. 写入文件(Write)
write(fd, "今天心情不错。", 18);
把内存中的内容写入到文件中
必须先用
open()
打开,才能write()
🔹 4. 读取文件(Read)
read(fd, buffer, 100);
你可以从文件中读取内容到内存里
读取之前也要先
open()
,否则读不了
🔹 5. 重新定位文件指针(Reposition)
lseek(fd, 0, SEEK_SET); // 移到开头
每次写或读,其实都有个“笔尖”在移动
lseek()
就是把“笔尖”移动到你想要的地方
🔹 6. 获取文件信息(Get File Attributes)
stat("mydiary.txt", &info);
你可以查看文件大小、创建时间、修改时间、权限等等
🔹 7. 关闭文件(Close)
close(fd);
用完文件必须关掉,告诉操作系统“我写完了,文件你可以放下了”
设备操作(Device Manipulation)
设备操作类系统调用,让程序可以读写硬件设备,例如:键盘、鼠标、打印机、磁盘、显示器等。
就像你按下一个键,系统把它变成文字,或你点击“打印”,系统就开始工作,这些都依赖于“设备操作”系统调用。
系统调用类别和说明:
1️⃣ request device
(请求设备)
向操作系统申请使用某个设备。
在操作系统中,一个进程请求访问设备时,会调用这样的系统调用,操作系统会:
检查设备是否空闲
如果空闲,则允许访问
否则让程序等待,或返回失败
2️⃣ release device
(释放设备)
使用完毕后通知操作系统“我用完了”。
如果忘记释放设备,可能会导致“设备被锁死”,其他进程用不了。
3️⃣ read
/ write
(读 / 写设备)
📖 从设备读取 / 📝 写入设备。
设备在操作系统中通常看作一种特殊的“文件”,因此可以对它读写:
read()
:如从键盘读取、从磁盘读取、从传感器获取数据write()
:如向打印机输出、向声卡发送音频流、向显示器输出图像
4️⃣ reposition
(重新定位设备读写指针)
📍 调整设备中读写的位置,常用于磁盘驱动器或串行设备。
比如你正在从一个音频设备读取数据,如果想跳过一段静音区域,你就要调整读取的位置。
5️⃣ get / set device attributes
🔍 查询 / ✏️ 设置设备的属性信息
get
:查看当前设备状态(开/关、剩余空间、连接状态、设备类型等)set
:配置设备参数,如波特率、分辨率、模式等
常用系统调用是 ioctl()
(input/output control)
类比:打印前查看是否缺纸(get),切换为双面打印(set)。
6️⃣ logically attach / detach devices
🔌 将设备逻辑上挂载或卸载进系统。
“Attach” 表示把设备“挂接”到操作系统中,准备使用(例如 USB 插入)
“Detach” 表示设备断开或被卸载(例如安全移除 U 盘)
操作系统通过这些调用维护设备与系统的关系。
类比:把 U 盘插入电脑(attach),写完东西后“安全弹出”(detach)
信息维护(Information Maintenance)
信息维护系统调用 让程序可以获取或设置系统信息,如当前时间、系统状态、文件属性、进程状态、设备信息等。
你可以把它理解为:
📋 “向操作系统打听情况” 或 “告诉操作系统更新信息”的官方手段
分类说明
1️⃣ get time or date
、set time or date
获取或设置当前时间和日期
获取系统时间:
gettimeofday()
(UNIX)设置系统时间:
settimeofday()
(需要管理员权限)
你问操作系统:“现在几点啦?”(get)管理员说:“把时间调到 8:00AM。”(set)
2️⃣ get system data
、set system data
获取或设置操作系统的配置信息或统计数据
系统内存使用情况
当前负载、在线用户数
操作系统版本
你问:“这台电脑还有多少内存?”
3️⃣ get attributes
(获取属性)
查询:
进程属性(如 PID、状态)
文件属性(大小、时间戳、权限)
设备状态(连接状态、使用状态)
示例系统调用:
stat()
:获取文件的元信息(大小、权限、时间)getpid()
:获取进程 PIDioctl()
:获取设备状态
就像你查看“某个文件多大、谁创建的”,或者“打印机有没有纸”。
4️⃣ set attributes
(设置属性)
修改:
文件权限(可读/可写/执行)
文件所有者(UID/GID)
进程优先级
设备参数(例如终端是否支持颜色)
类比:给文件贴上“禁止修改”标签(只读),或将文件“转让”给另一个用户。
通信(Communications)
通信类系统调用用于让不同的“进程(程序)”之间相互发送消息、共享数据、同步状态,不管这些进程是在同一台电脑上,还是不同的电脑上。
你可以把它理解成:“程序之间的微信聊天 + 文件共享 + 远程协作”。
通信的两种主要方式:
类型 | 描述 | 举例 |
---|---|---|
🖥️ 进程间通信(IPC) | 两个程序在同一台计算机上通信 | 浏览器和下载器协作 |
🌐 网络通信 | 两个程序在不同计算机上通信 | 微信客户端和服务器之间通信 |
通信类系统调用详解
1️⃣ create communication connection
(建立通信连接)
程序首先需要“建立一条通道”才能进行通信,就像打电话前要拨号。
类比:A 程序说:“我要和 B 程序通话,先建立一条管道。”
2️⃣ delete communication connection
(断开通信)
通信完成后需要关闭连接,以节省资源。
类比:“电话打完了,挂掉。” 或 “关闭聊天室。”
3️⃣ send / receive messages
(发送/接收消息)
通信的核心就是发送消息和接收消息。
4️⃣ transfer status information
(传递状态信息)
进程不止传递消息,有时候还要“告知对方我现在状态如何”:
比如“我已经准备好”、“我完成了”、“请等一下”。
比如你和同事协作时说:“我完成第 1 步了,你可以继续做第 2 步了。”
5️⃣ attach / detach remote devices
(挂接/卸载远程设备)
这个功能出现在网络分布式系统中,比如:
远程挂接一台打印机
在一台电脑上远程访问另一台电脑的硬盘