目录
引言
基本概念
1. 进程(Process)
2. 线程(Thread)
线程编程实战
1. 常见线程库
2. 合理设置线程数
3. pthread 创建线程
线程同步机制
1. 互斥锁 pthread_mutex_t
2. 条件变量 pthread_cond_t
3. 读写锁 pthread_rwlock_t
进程的创建与控制
1. fork
2. exec
3. system
4. popen 管道读取输出
进程间通信 IPC 详解
1. 方式对比表:
2. 信号 signal
3. 共享内存 POSIX
总结
引言
本文深入探讨了 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