#include
#include
pid_t fork(void);
关键特性:
errno
获取具体错误)当fork()被调用时,内核会:
特别注意:
copy-on-write
技术优化内存复制特性 | fork() | vfork() |
---|---|---|
地址空间 | 完全复制(COW机制) | 共享父进程空间 |
执行顺序 | 调度器决定 | 保证子进程先运行 |
性能消耗 | 较高(需复制页表) | 极低 |
使用场景 | 通用进程创建 | 立即exec的场景 |
典型vfork使用模式:
pid_t pid = vfork();
if (pid == 0) {
execl("/bin/ls", "ls", "-l", NULL);
_exit(127); // 仅在exec失败时执行
}
#include
#include
#include
#define TASK_COUNT 5
void worker(const std::string& task) {
std::cout << "Processing " << task
<< " in pid:" << getpid() << std::endl;
sleep(1); // 模拟任务执行
}
int main() {
const char* tasks[TASK_COUNT] = {
"face_detection", "object_recognition",
"action_analysis", "hat_detection",
"feature_extraction"
};
std::vector<pid_t> children;
// 创建进程池
for (int i = 0; i < TASK_COUNT; ++i) {
pid_t pid = fork();
if (pid == 0) {
worker(tasks[i]);
exit(EXIT_SUCCESS); // 明确终止子进程
} else if (pid > 0) {
children.push_back(pid);
} else {
perror("fork failed");
exit(EXIT_FAILURE);
}
}
// 父进程等待所有子进程
for (pid_t pid : children) {
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
std::cout << "Child " << pid
<< " exited with status "
<< WEXITSTATUS(status) << std::endl;
}
}
return EXIT_SUCCESS;
}
进阶技巧:
WNOHANG
选项实现非阻塞等待SIGCHLD
信号处理避免僵尸进程setpgid()
创建进程组#include
#include
// 创建信号量集
int sem_id = semget(IPC_PRIVATE, 1, 0666|IPC_CREAT);
semctl(sem_id, 0, SETVAL, 0); // 初始化为0
struct sembuf ops = {0, 1, 0}; // 对信号量0执行V操作
if (fork() == 0) {
// 子进程先执行
printf("Child process working...\n");
semop(sem_id, &ops, 1); // 通知父进程
exit(0);
} else {
// 父进程等待信号量
semop(sem_id, &ops, -1); // P操作等待
printf("Parent process continues\n");
semctl(sem_id, 0, IPC_RMID); // 清理
}
struct task_msg {
long mtype; // 必须作为第一个字段
int task_id;
char task_name[32];
float priority;
};
// 创建增强型消息队列
int msgq_create() {
key_t key = ftok("/tmp", 'A');
int msgid = msgget(key, IPC_CREAT|0666);
if (msgid == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
return msgid;
}
void send_complex_task(int msgid, const struct task_msg* msg) {
if (msgsnd(msgid, msg, sizeof(*msg)-sizeof(long), 0) == -1) {
perror("msgsnd failed");
exit(EXIT_FAILURE);
}
}
void receive_task(int msgid, long type, struct task_msg* msg) {
ssize_t n = msgrcv(msgid, msg, sizeof(*msg)-sizeof(long),
type, 0);
if (n == -1) {
perror("msgrcv failed");
exit(EXIT_FAILURE);
}
}
性能优化建议:
IPC_NOWAIT
标志实现非阻塞操作MSG_NOERROR
截断过大数据机制 | 带宽(MB/s) | 延迟(μs) | 适用场景 |
---|---|---|---|
匿名管道 | 500-800 | 1-3 | 父子进程简单通信 |
System V消息队列 | 50-100 | 10-30 | 结构化消息传递 |
POSIX共享内存 | 2000-5000 | 0.5-2 | 高频大数据量交换 |
Unix域套接字 | 1000-2000 | 5-10 | 全双工复杂通信 |
#include
void create_process_tree(int depth) {
if (depth <= 0) return;
pid_t pid = fork();
if (pid == 0) {
prctl(PR_SET_NAME, "worker_process"); // 设置进程名
create_process_tree(depth - 1);
while(1) pause(); // 模拟工作
} else if (pid > 0) {
printf("Created child %d at level %d\n", pid, depth);
} else {
perror("fork failed");
}
}
系统工具整合:
pstree -p
查看进程树结构top -H
监控各进程资源占用cgroups
实现资源限制#define CHECK_FORK(pid) \
do { \
if ((pid) == -1) { \
fprintf(stderr, "[%s:%d] fork failed: %s\n", \
__FILE__, __LINE__, strerror(errno)); \
exit(EXIT_FAILURE); \
} \
} while(0)
// 使用示例
pid_t pid = fork();
CHECK_FORK(pid);
性能测试建议:
time
命令测量实际执行时间perf stat
分析CPU利用率valgrind
检查内存使用情况通过本文的深度技术解析和实战代码示例,读者应该已经建立了完整的Linux多进程编程知识体系。建议读者在自己的项目中尝试实现:
记住:多进程编程的核心在于平衡"隔离性"与"通信开销",合理的设计往往比盲目的并行化更能提升系统性能。