下面是详细讲解创建子进程的实例教程。
什么是子进程?
在Linux系统中,一个进程可以创建其他进程。被创建的进程称为子进程,而新创建进程的进程称为父进程。子进程继承了父进程的所有属性和资源,包括进程ID、打开的文件描述符、信号处理方式等。
如何创建子进程?
Linux中使用C语言提供了 fork()
函数来创建子进程。fork()
函数是一个系统调用,调用后会在调用进程中复制出一个新进程,这个新进程就是子进程,同时复制出来的新进程会和原进程一样执行 fork()
之后的代码。
#include <unistd.h>
pid_t fork(void);
成功调用 fork()
函数后,会返回两个值:子进程中返回0;父进程中返回子进程的进程ID(PID)。
下面是一个简单的示例,展示了如何使用 fork()
函数创建子进程:
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid;
printf("Before fork\n");
pid = fork();
if (pid == -1) {
perror("Fork failed");
return -1;
} else if (pid == 0) { // child process
printf("I am the child process\n");
printf("My PID is %d\n", getpid());
} else { // parent process
printf("I am the parent process\n");
printf("My child's PID is %d\n", pid);
}
printf("After fork\n");
return 0;
}
运行程序,可以看到输出:
Before fork
I am the child process
My PID is 1234
After fork
I am the parent process
My child's PID is 1234
After fork
子进程的运行顺序
在实际场景中,子进程和父进程的运行顺序是不能确定的。因此,在使用 fork()
函数创建子进程时,我们应该始终确保子进程和父进程是交替运行的。这需要我们在代码中进行特殊处理。
我们还以一个具体的服务端与客户端通信过程为例:
- 服务端监听本地的某个端口,等待客户端连接
- 当服务端接收到连接请求时,创建一个子进程处理该连接
- 父进程继续监听连接请求
以下是代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#define MAXLINE 4096
#define SERV_PORT 9877
void do_echo(int sockfd);
int main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd < 0) {
perror("socket error");
return -1;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("bind error");
return -1;
}
if (listen(listenfd, 10) < 0) {
perror("listen error");
return -1;
}
for (;;) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
if (connfd < 0) {
perror("accept error");
continue;
}
if ((childpid = fork()) == 0) { // In child process
close(listenfd);
do_echo(connfd);
exit(0);
}
close(connfd); // In parent process
}
return 0;
}
void do_echo(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
for (;;) {
memset(buf, 0, MAXLINE);
n = read(sockfd, buf, MAXLINE);
if (n < 0) {
if (errno == EINTR) {
continue;
} else {
perror("read error");
break;
}
} else if (n == 0) {
printf("client closed connection\n");
break;
}
write(sockfd, buf, n);
}
close(sockfd);
}
运行服务端程序,可以看到输出:
accepted connection from 127.0.0.1:56178
accepted connection from 127.0.0.1:56180
然后可以在客户端向服务端发送数据,服务端会回显收到的数据。
总结
本文详细讲解了如何在Linux中使用C语言的fork()函数创建子进程,并且提供了两个实例来巩固理解。子进程和父进程的运行顺序是不能确定的,因此在使用时需要注意编写代码,保证子进程和父进程的交替执行。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux中使用C语言的fork()函数创建子进程的实例教程 - Python技术站