目录
引言
本文深入探讨了 C 语言中多线程编程、进程间通信(IPC)机制的底层实现,涵盖线程同步、信号量、互斥锁、共享内存等关键知识,并通过实际任务案例带你走进操作系统世界中的“线程宇宙”
基本概念
1. 进程(Process)
程序的一次执行过程,是操作系统进行资源分配的最小单位。
一个程序至少有一个进程。
每个进程有自己的 地址空间、资源集合 和 执行上下文。
进程分类:
前台进程
后台进程
服务进程(如守护进程)
运行在服务器上一般都是守护进程。
2. 线程(Thread)
线程是进程中独立的执行单元,是程序执行的最小单位。
一个进程至少有一个主线程(main thread)。
多个线程共享该进程的地址空间和资源。
线程拥有自己的 栈空间 和 寄存器上下文。
线程编程实战
1. 常见线程库
POSIX Thread:
pthread
(C语言中最常用)OpenMP:并行处理,适合 C/C++
C++11
std::thread
(不在本文范围)
2. 合理设置线程数
// CPU 密集型:核心线程数 ≈ CPU数 + 1
// IO 密集型:核心线程数 ≈ ((线程等待时间 / 线程CPU时间) + 1) * CPU数
3. pthread 创建线程
#include <pthread.h>
void *thread_func(void *arg) {
printf("This is a new thread\n");
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL); // 等待线程结束
return 0;
}
线程同步机制
线程同时访问共享资源时容易引发竞态条件,需进行同步。
1. 互斥锁 pthread_mutex_t
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_unlock
pthread_mutex_destroy
2. 条件变量 pthread_cond_t
用于线程间等待与唤醒的机制。
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex); // 释放锁并阻塞
pthread_cond_signal(&cond); // 唤醒一个线程
pthread_mutex_unlock(&mutex);
3. 读写锁 pthread_rwlock_t
适用于读多写少的场景。
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
pthread_rwlock_rdlock(&rwlock); // 读锁
pthread_rwlock_unlock(&rwlock);
pthread_rwlock_wrlock(&rwlock); // 写锁
pthread_rwlock_unlock(&rwlock);
进程的创建与控制
1. fork
克隆当前进程,创建子进程。
pid_t pid = fork();
if (pid == 0) {
// 子进程
} else {
// 父进程
}
2. exec
用新程序替换当前进程的映像。
execl("/bin/ls", "ls", "-l", NULL);
3. system
执行 shell 命令,本质是 fork + exec 的封装。
system("ls -l");
4. popen
管道读取输出
进程间通信 IPC 详解
1. 方式对比表:
方式 | 特点 | 是否跨进程 | 是否阻塞 | 适用场景 |
---|---|---|---|---|
管道 | 简单易用 | 是 | 是 | 父子进程 |
信号 | 异步通知机制 | 是 | 否 | 异常处理 |
信号量 | 原子性控制 | 是 | 是 | 多进程同步 |
共享内存 | 访问速度最快 | 是 | 否 | 大数据共享 |
消息队列 | 异步通信 | 是 | 否 | 有序通信 |
套接字 | 网络/本地通信 | 是 | 是/否 | 客户端/服务端通信 |
2. 信号 signal
#include <signal.h>
void handler(int sig) {
printf("Caught signal %d\n", sig);
}
int main() {
signal(SIGINT, handler); // 注册 ctrl+C 的信号处理
while (1) pause();
}
3. 共享内存 POSIX
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
int fd = shm_open("/shm_name", O_CREAT | O_RDWR, 0666);
ftruncate(fd, 4096);
void *ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// 写入共享内存
strcpy((char*)ptr, "Hello from shared memory");
munmap(ptr, 4096);
close(fd);
shm_unlink("/shm_name");
总结
通过本文的学习,我们系统掌握了 C 语言中进程与线程的基本概念、线程创建与同步的编程方法,以及多种进程间通信(IPC)机制,包括信号、共享内存、信号量等。进程负责资源的独立管理,线程则提供更轻量级的并发执行方式;同步机制确保了多线程环境下数据的一致性,而 IPC 则使得多个进程间能够高效协作与通信。结合实际案例,我们不仅加深了对操作系统底层原理的理解,也提升了并发编程与系统开发的能力。对于从事系统编程、服务器开发或学习操作系统的同学,这些内容都是必不可少的核心知识。
更多代码可以观看:Niuer_C: C语言学习 0711-0721