Linux网络编程入门 互动版

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

1.进程

并发服务端:最简单的实现方式,用fork函数为每个客户端创建个子进程。 在介绍前,先回顾下进程的概念。

(1)在操作系统中,进程是程序的一次执行,且是拥有资源的最小单位和调度单位(在引入线程的操作系统中,线程是最小的调度单位)。一个进程,包括代码、数据和分配给进程的资源。

(2)在Linux系统中创建进程有两种方式:一是由操作系统创建,二是由父进程创建进程。

2.fork

fork函数的Linux头文件以及函数定义如下:

#include <unistd.h>
pid_t fork(void)

(1)当一个进程(该进程相当于父进程 )调用fork函数后,系统先给新的进程(子进程)分配资源,例如存储数据和代码的空间,然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆 了一个自己。 简而言之,父进程就像父亲,子进程就像儿子,父进程克隆产生子进程,因此父进程和子进程代码、指令、变量等都相同。

(2)通过fork返回的值来判断当前进程是子进程还是父进程。fork函数返回两次 ,即在父进程中fork返回值是子进程的ID号,在子进程中fork返回值是0。如果出错,返回-1。

  • 在父进程中,fork返回新创建子进程的进程ID
  • 在子进程中,fork返回0
  • 如果出现错误,fork返回一个负值-1

(3)每个进程都有一个独特(互不相同)的进程标识符(process ID),可以通过getpid函数获得当前进程的ID,同时也可以通过getppid函数获得父进程的ID。

写个程序理解fork函数,如下:

#include <stdio.h>
#include <unistd.h>

int main()
{
    pid_t pid = fork();

    if (pid == -1) {
        printf("fork error\n");
    } else if (pid == 0) {
        printf("我是子进程, 我的进程ID是 %d\n",getpid());
        printf("我的父进程ID是 %d\n",getppid());
    } else {
        printf("我是父进程, 我的进程ID是%d\n",getpid());
    }
    sleep(1);
    return 0;
}

第6行fork执行完毕后,出现两个进程,如下图所示,fork是把进程当前的情况拷贝一份,因此父进程和子进程有共同的代码、指令以及变量。但这两个进程的变量都是独立的,存在不同的内存地址中。根据判断条件(fork的返回值),从而可以执行相应代码。

10

第16行执行sleep函数,挂起一段时间,保证父/子进程执行完毕。

执行完毕,结果如下图所示。

11

在右侧建立个名为fork的c文件,试编写个程序:测试个fork函数。