在操作系统中,进程和线程是执行程序的基本单元。父子进程与线程之间的关系是操作系统中一个重要且复杂的主题。本文将深入探讨父子进程与线程的创建、通信与协作技巧。
父子进程的创建
在大多数操作系统中,父进程通过调用系统调用(如fork())创建子进程。以下是使用C语言在Unix-like系统中创建父子进程的示例代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork(); // 创建子进程
if (pid == -1) {
// fork失败
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程
printf("Hello from child process!\n");
_exit(0); // 子进程立即退出
} else {
// 父进程
printf("Hello from parent process!\n");
wait(NULL); // 等待子进程结束
}
return 0;
}
父子线程的创建
与进程类似,父线程可以通过调用系统调用(如pthread_create())创建子线程。以下是在C语言中使用POSIX线程库创建父子线程的示例代码:
#include <stdio.h>
#include <pthread.h>
void* child_thread_func(void* arg) {
printf("Hello from child thread!\n");
return NULL;
}
int main() {
pthread_t child_thread;
if (pthread_create(&child_thread, NULL, child_thread_func, NULL) != 0) {
perror("pthread_create");
return 1;
}
printf("Hello from parent thread!\n");
pthread_join(child_thread, NULL); // 等待子线程结束
return 0;
}
父子进程/线程的通信
父子进程/线程之间可以通过多种方式进行通信,如管道(pipe)、信号(signal)、共享内存(shared memory)和消息队列(message queue)等。
管道
管道是一种简单的进程间通信机制。以下是一个使用管道进行父子进程通信的示例:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pid_t pid;
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
pid = fork();
if (pid == -1) {
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程
close(pipefd[0]); // 关闭读端
write(pipefd[1], "Hello from child!\n", 18);
close(pipefd[1]); // 关闭写端
_exit(0);
} else {
// 父进程
close(pipefd[1]); // 关闭写端
char buffer[20];
read(pipefd[0], buffer, sizeof(buffer));
printf("%s", buffer);
close(pipefd[0]); // 关闭读端
wait(NULL); // 等待子进程结束
}
return 0;
}
共享内存
共享内存是一种高效的进程间通信机制。以下是一个使用共享内存进行父子进程通信的示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
const char* msg = "Hello from child!";
size_t size = sizeof(msg);
int shm_fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
perror("shm_open");
return 1;
}
if (ftruncate(shm_fd, size) == -1) {
perror("ftruncate");
return 1;
}
void* addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程
memcpy(addr, msg, size);
_exit(0);
} else {
// 父进程
char buffer[20];
memcpy(buffer, addr, size);
printf("%s\n", buffer);
munmap(addr, size);
shm_unlink("/my_shm");
wait(NULL); // 等待子进程结束
}
return 0;
}
父子进程/线程的协作
父子进程/线程之间的协作通常涉及到同步机制,如互斥锁(mutex)、条件变量(condition variable)和信号量(semaphore)等。
互斥锁
以下是一个使用互斥锁进行父子进程/线程协作的示例:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t lock;
void* child_thread_func(void* arg) {
pthread_mutex_lock(&lock);
printf("Hello from child thread!\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main() {
pthread_t child_thread;
if (pthread_mutex_init(&lock, NULL) != 0) {
perror("pthread_mutex_init");
return 1;
}
if (pthread_create(&child_thread, NULL, child_thread_func, NULL) != 0) {
perror("pthread_create");
return 1;
}
pthread_mutex_lock(&lock);
printf("Hello from parent thread!\n");
pthread_mutex_unlock(&lock);
pthread_join(child_thread, NULL); // 等待子线程结束
pthread_mutex_destroy(&lock);
return 0;
}
通过以上示例,我们可以了解到父子进程/线程的创建、通信与协作技巧。在实际应用中,根据具体需求选择合适的机制和工具,才能确保程序的正确性和效率。
