C语言中的进程、线程与进程间通信详解

发布于:2025-08-11 ⋅ 阅读:(23) ⋅ 点赞:(0)

目录

引言

基本概念

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


网站公告

今日签到

点亮在社区的每一天
去签到