进程

1. 进程、进程组、会话

进程(process)属于进程组(group),进程组属于会话(session)


2. 守护进程的创建

  • 父进程 fork() 产生子进程,父进程退出.这样做保证即将要成为会话组长的进程,调用setsid()能调用成功

  • 父进程先于子进程退出后,子进程,被init进程收养,调用setsid(),脱离init进程控制,成为会话组长,并与原来的登录会话和进程组脱离,同时脱离终端的控制。

  • 会话组长可以重新代开控制终端,那么可以使该进程再fork()一次,然后父进程退出,产生的子进程被init进程收养,最终,得到的进程,具备: 脱离终端控制,处在于一个新的会话组,并且不是会话组长

  • 关闭所有从父进程继承的不再需要的文件描述符

    1
    2
    3
    4
    for (int i = 0; i < NOFILE; ++ i)
    {
    close(i);
    }
  • 改变当前工作目录
    进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmp,调用 chdir("/")

  • 重设文件创建掩模
    进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0)

  • 处理SIGCHLD信号
    处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。
    signal(SIGCHLD,SIG_IGN)


3. 孤儿进程 僵死进程

两句话可以概括:

  • 孤儿进程: 父进程先于子进程退出,那么,该子进程就会成为孤儿进程,被init进程收养
  • 僵死进程:子进程退出时,父进程没有调用wait()waitpid()函数,子进程的空间得不到释放,操作系统无法回收物理空间,造成内存泄漏。

4. 进程优先级

调用nice()函数