UNIX再学习 -- 进程关系
APUE 第 10 章信号讲完,回过头来看一下第 9 章的进程关系。终端登录和网络登录部分,我们只讲 Linux 系统的。
一、终端登录
Ctrl+Alt切换到Windows
Ctrl+Alt+F7 退出纯命令模式。
我们来看一下,进入纯命令模式界面:
4.密码验证无误后,login 将切换目录到用户的 home 目录,改变该终端设备的权限,login 进程改变为登录用户 ID 并调用改用户的登录 shell:execl(“/bin/sh”,”-sh”,(char *)0)
5.登录shell读取其启动文件 (Bourne shell) 和 Korn shell。
从 getty 开始 exec 到 login,再 exec 到 bash,其实都是同一个进程,因此控制终端没变,文件描述符 0、1、2 也仍然指向控制终端。由于 fork 会复制 PCB 信息,所以由 Shell 启动的其它进程也都是如此。
二、网络登录
三、进程组 ID
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); 返回:调用进程的进程 ID
pid_t getppid(void); 返回:调用进程的父进程 ID
uid_t getuid(void); 返回:调用进程的实际用户 ID
uid_t geteuid(void); 返回:调用进程的有效用户 ID
gid_t getgid(void); 返回:调用进程的实际组 ID
gid_t getegid(void); 返回:调用进程的有效组 ID
注意,这些函数都没有出错返回
(1)示例说明
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); return 0;
}
输出结果:
pid = 3028
ppid = 2808
uid = 0
euid = 0
gid = 0
egid = 0
//每次执行结果都不一定相同
每个进程除了有一个进程 ID 之外,还属于一个进程组。我们讲信号的时候,有提到过。那时不知道啥意思。
#include <unistd.h>int setpgid(pid_t pid, pid_t pgid);pid_t getpgid(pid_t pid);pid_t getpgrp(void); /* POSIX.1 version */pid_t getpgrp(pid_t pid); /* BSD version */int setpgrp(void); /* System V version */int setpgrp(pid_t pid, pid_t pgid); /* BSD version */
可以看出系统不同用的函数也不同,建议使用 POSIX.1 规定中的无参数 getprgp() 函数。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());return 0;
}
输出结果:
pid = 3497
ppid = 3401
uid = 0
euid = 0
gid = 0
egid = 0
-----------------
pgrp = 3497
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());if (-1 == (setpgid (0, getppid ())))perror ("setpgid"), exit (1);printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());return 0;
}
输出结果:
pid = 3593
ppid = 3401
uid = 0
euid = 0
gid = 0
egid = 0
-----------------
pgrp = 3593
-----------------
pgrp = 3401
四、 会话
会话(session)是一个或多个进程组的集合。
1、进程调用 setsid 函数建立一个新会话。
#include <unistd.h>
pid_t setsid(void);
返回值:成功返回进程组 ID;失败返回 -1
函数解析:
如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新会话。具体会发生以下 3 件事。
示例说明:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());
/*if (-1 == (setpgid (0, getppid ())))perror ("setpgid"), exit (1);printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());*/if(setsid() == -1)perror ("setsig"), exit (1);return 0;
}
输出结果:
pid = 3738
ppid = 3401
uid = 0
euid = 0
gid = 0
egid = 0
-----------------
pgrp = 3738
setsig: Operation not permitted
示例解析:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());if (-1 == (setpgid (0, getppid ())))perror ("setpgid"), exit (1);printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());pid_t sig = setsid ();if(sig == -1)perror ("setsig"), exit (1);printf ("sig = %d\n", sig);return 0;
}
输出结果:
pid = 3771
ppid = 3401
uid = 0
euid = 0
gid = 0
egid = 0
-----------------
pgrp = 3771
-----------------
pgrp = 3401
sig = 3771
2、getsid 函数返回会话首进程的进程 ID
#include <unistd.h>
pid_t getsid(pid_t pid);
返回值:成功返回会话首进程的进程组 ID;失败返回 -1
(1)函数解析
(2)示例说明
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main (void)
{ printf ("pid = %d\n", getpid ()); printf ("ppid = %d\n", getppid ()); printf ("uid = %d\n", getuid ()); printf ("euid = %d\n", geteuid ()); printf ("gid = %d\n", getgid ()); printf ("egid = %d\n", getegid ()); printf ("-----------------\n");printf ("pgrp = %d\n", getpgrp ());//pid 为 0printf ("sid = %d\n", getsid (0));return 0;
}
输出结果:
pid = 3809
ppid = 3401
uid = 0
euid = 0
gid = 0
egid = 0
-----------------
pgrp = 3809
sid = 3401
五、控制终端
六、作业控制
七、shell 执行程序
使用 ps 命令,首先使用不支持作业控制的、在 Solaris 上运行的经典 Bourne shell。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main (void)
{ pid_t pid, pr; pid = fork (); if (pid == -1) perror ("fail to fork"), exit (1); else if (pid == 0) { printf ("这是子进程 pid = %d", getpid ()); printf ("父进程的 ppid = %d\n", getppid ()); } else { pr = wait (NULL); //while (1); sleep (10); //可以保证子进程先被调度 printf ("这是父进程 ppid = %d\n", getpid ()); } return 0;
} 实验:
在一个终端执行 ./a.out
# ./a.out
这是子进程 pid = 3951父进程的 ppid = 3950
(十秒后)
这是父进程 ppid = 3950 在另一个终端,查看进程信息
# ps -C a.out -o pid,ppid,pgid,sid,comm PID PPID PGID SID COMMAND3950 3868 3950 3868 a.out
UNIX再学习 -- 进程关系相关推荐
- UNIX再学习 -- 守护进程(转)
参看:守护进程 一.什么是守护进程 守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程.它是一个生存期较长的进程,通常独立于控制 ...
- UNIX再学习 -- 内存管理
C 语言部分,就一再的讲内存管理,参看:C语言再学习 -- 再论内存管理 UNIX.Linux 部分还是要讲,足见其重要. 一.存储空间布局 1.我们先了解一个命令 size,继而引出我们今天要讲的 ...
- UNIX再学习 -- 线程
终于要讲到线程部分,线程和进程让人够头痛的内容. 一.线程概念 老样子,我们还是按我们讲进程时的方式说起,参看:UNIX再学习 -- 进程环境 首先需要了解下,什么是线程. Linux 下的线程,可能 ...
- UNIX再学习 -- 信号
终于讲到信号部分,很多比较重要的应用程序都需处理信号.第 9 章需要先了解信号机制再看,所以先跳过不讲.现在开始详解信号. 一.信号概念 信号是提供异步事件处理机制的软件中断. 这些异步事件可能来自硬 ...
- UNIX再学习 -- 用户 ID 和组 ID
用户 ID和组 ID 的内容已经在好几章中出现过了.之前都没有讲到,现在放到一起总结. 一.用户 ID 和 组 ID 回顾 1.我们在APUE 第 4.6.8 章,都有涉及到. 其中我们用到的地方: ...
- UNIX再学习 -- exec 函数族
我们在讲,文件I/O的时候,简单提到过 exec 函数,讲到 vfork 的时候,也有用到.下面我们来详细介绍下它. 参看:UNIX再学习 -- 文件I/O 参看:UNIX再学习 -- 函数 for ...
- UNIX再学习 -- exit 和 wait 系列函数
我们一开始讲进程环境时,就有提到了.进程有 8 种方式使进程终止. 其中 5 种为正常终止,它们是: (1)在 main 函数中执行 return (2)调用 exit 函数,并不处理文件描述符,多进 ...
- UNIX再学习 -- 死磕内存管理
malloc/free简化实现:malloc 和 sbrk 关系:虚拟内存机制. 一个内存管理 C 语言部分讲,UNIX部分讲,Linux部分还讲,死磕到底!! 一.mallc/free简化实现 上篇 ...
- UNIX再学习 -- shell编程
UNIX环境高级编程看了三章,遇到不少重定向等shell命令.本想到Linux时再讲,看来有必要提前了.之前有看过一本<嵌入式Linux软硬件开发详解>这本书里有简单介绍了一部分shell ...
最新文章
- 从HelloWorld看Knative Serving代码实现
- 【sox】使用sox增加混响效果
- 页面导航的基础与深入
- 1.2开发文档简读,了解全貌.mp4
- ecs服务器数据迁移_如何非常方便地从Windows文件服务器把数据完整地迁移到ONTAP Select...
- 基于JAVA+SpringMVC+Mybatis+MYSQL的高校后勤管理系统
- CCFA中国国际零售创新大会,观远数据用智能分析驱动零售决策
- 机器 – 程序 – 人 (2)
- Foxconn Core Concept
- HashMap遍历有序性问题——map.entrySet()的无序性
- 有道云 语法高亮_antlr语法增强使用
- 北师范《计算机导论》在线作业,福建师范大学17年8月《计算机导论》作业考核试题答案材料...
- 计算机设置密码打印机无法共享,win7设置开机密码后无法连接共享打印机
- “绿水青山就是金山银山”
- 制作Linux的优盘(usb)启动盘
- 一个好的学习方法——MAS 学习法
- 洛谷 P2530 [SHOI2001]化工厂装箱员
- java.nio.file.NoSuchFileException异常解决
- 关闭Delphi2010出现以下bpl错误,解决方案.
- 仿网易云音乐新版详情页(沉浸式状态栏,上滑隐藏)