热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UNIX环境高级编程进程关系

    相关函数列表 //返回调用进程的进程组ID#includ



 

 


相关函数列表

//返回调用进程的进程组ID
#include
pid_t getpgrp(void);
pid_t getpgid(pid_t pid);
//getpgid(0) 等于 getpgrp()
//创建一个新会话
#include
pid_t setsid(void);
pid_t getsid(get_t pid); //返回会话首进程的进程组ID
//对于setsid()函数,如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新会话
//1.该进程变成新会话的会话首进程(session leader会话首进程是创建该会话的进程),此时,该进程
// 是新会话中唯一进程
//2.该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程ID
//3.该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,那么这种联系也被切断
//根据FD获取哪个进程组是前台进程组
#include
pid_t tcgetpgrp(int fd);
int tcsetpgrp(int fd, pid_t pgrpid);
//给出控制TTY的文件描述符,下面函数可以获得会话首进程的进程组ID
#include
pid_t tcgetsid(int fd);

 

 

 


终端登录

系统管理者创建/etc/ttys文件,之后init进程读取这个文件,然后fork新进程执行exec调用getty程序

getty对终端设备调用open函数,以读写方式将终端打开,一旦设备打开,则文件描述符就被设置到该设备,然后getty输出“login”之类的信息。getty会根据波特率适当的更改终端的速度。

当用户输入用户名后,getty工作就完成了,然后它调用login程序

execle("/bin/login", "login" "-p", username, (char*)0, envp);

最初的init进程有超级用户权限,所以它fork后的进程都有超级用户权限 

login能处理多项工作,得到用户名调用getpwnam取得相应的用户口令,然后调用getpass提示"password",用户输入口令后,调用crypt将用户口令加密,并与阴影文件的pw_passwd字段比较,如果出错则login调用exit表示登陆失败,父进程init了解到子进程情况后再次调用fork又执行getty,重复上述过程


UNIX环境高级编程 进程关系

如果用户登陆正常login就将完成如下工作:

1)将当前工作目录更改为用户的起始目录(chdir)

2)调用chown更改该终端的所有权,使登陆用户成为它的所有者

3)将对该终端设备的访问权限改变为“用户读和写”

4)调用setgid以及initgroups设置进程的组ID

5)用login得到所有信息初始化环境:起始目录(HOME),shell(SHELL),用户名(USER和LOGNAME)以及一个

   系统默认路径(PATH)

6)login进程更改为登陆用户的用户ID(setuid)并调用该用户的登陆shell,其方式类似于

execl("/bin/sh", "-sh", (char*)0);

 

 


网络登陆

init进程调用一个shell,使其执行shell脚本/etc/rc,由此shell脚本启动一个守护进程inetd。一旦shell脚本终止,inetd的父进程就变成init。inetd等待TCP连接达到主机,然后执行一次fork,生成子进程exec执行适当的程序。

当telnet请求达到后,inetd会fork一个进程,然后执行telnetd程序(exec调用),之后分成两个进程,父进程继续处理连接的通讯,子进程执行login程序,父进程和子进程通过伪终端相连接。

执行过程:

1.init调用fork和exec启动inetd

2.inetd接收到客户端的telnet连接,然后fork新进程

3.inetd继续接受客户来的连接,新进程调用exec启动telnetd处理用户逻辑

 


会话

进程组是一个或多个进程的集合,会话是一个或多个进程组的集合

比如proc1 | proc2 & | proc3 | proc4 | proc5

 

会话和进程组还有一些其他特性

1.一个会话可以有一个控制终端(controlling terminal),这通常是终端设备(在终端登录)或伪终端设备(网络)

2..建立与控制终端连接的会话首进程被称为控制进程(controlling process)

3.一个会话中的几个进程组可被分成一个前台进程组(foreground process group)以及一个或多个后台进程

   组(background process group)

4.如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组

5.无论何时键入终端的中断键,都会将终端信号发送至前台进程组的所有进程

6.如果终端接口检测到调制解调器(或网络)已断开连接,则将挂断信号发送至控制进程(会话首进程)


UNIX环境高级编程 进程关系


 

 

 


作业控制

允许在一个终端上启动多个作业(进程组),它控制一个作业可以访问该终端以及哪些作业在后台运行。要求以下三种形式的支持:

1.支持作业控制的shell

2.内核中的终端驱动程序必须支持作业控制

3.内核必须提供对某些作业控制信号的支持

 

//这里启动了两个作业
pr *.c | lpr &
make all &
//在后台运行,之后又将作业1号变为前台运行
cat > temp.foo &
fg %1
stty tostop //禁止作业输出至控制终端

 对于前台,后台作业以及终端驱动程序的作业控制功能总结




UNIX环境高级编程 进程关系


 



 

 


shell执行程序

//执行下面这段shell
ps -o pid,ppid,pgid,sid,tpgid,comm | cat | cat | tail | more | head
//结果
PID PPID PGID SID TPGID COMMAND
26383 26381 26383 26383 26514 bash
26456 26383 26450 26383 26514 more
26514 26383 26514 26383 26514 ps
26515 26383 26514 26383 26514 cat
26516 26383 26514 26383 26514 cat
26517 26383 26514 26383 26514 tail
26518 26383 26514 26383 26514 more
26519 26383 26514 26383 26514 head

 从结果中可以看到,所有的命令都父进程ID都是bash,也就是bash去启动了那些命令

而ps,cat,cat,tail,more,head这些命令是在一个进程组中的。同时上面所有的进程都是在一个会话中

Bourne shell执行管道ps | cat1 | cat2时的进程


UNIX环境高级编程 进程关系


这里执行的sh后,又会fork一个新进程,然后这个新的sh进程再去fork一些子进程,fork的这些子进程都是执行

sh命令,这些sh命令又调用exec函数执行不同的shell命令,比如ps,cat这样的

管道中最后一个shell命令是由最初的sh(PID为202)调用exec执行的

当然这里不同的sh执行会有不同的效果,而且创建的进程顺序也会不同

linux上的bash shell对于所有的执行的管道命令都是bash的子进程 

 


通过pstree命令执行

ps -o pid,ppid,gid,sid,comm | cat | more | head | pstree
//结果
init-+-bash
|-6*[mingetty]
|-sshd---sshd-+-bash
| `-bash-+-cat
| |-head
| |-more
| |-ps
| `-pstree
`-udevd

可以看到init进程for了sshd(也就是终端),然后sshd又fork了bash,

bash调用exec再fork了cat,head,more,ps等命令,生成相应的进程

 

 

 


孤儿进程组

一个其父进程已经终止的进程称为孤儿进程(orphan process),这种进程由init进程收养,而整个进程组也有可能成为孤儿。

POSIX.1将孤儿进程组(orphaned process group)定义为:

该组中每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。

对孤儿进程组的另一种描述可以使:

一个进程组不是孤儿进程组的条件是---该组中有一个进程,其父进程在属于同一会话的另一个组中。如果进程组

不是孤儿进程组,name在属于同一会话另一个组中的父进程就有机会重新启动该组中停止的进程。在这里,进程组中每一个进程的父进程都属于另一个会话。所以此进程组是孤儿进程组。

 

 

 


FreeBSD实现

会话和进程组的FreeBSD实现


UNIX环境高级编程 进程关系


session结构体

1)s_count是该会话中的进程组数。当此计数器减至0时,则可释放此结构

2)s_leader是指向会话首进程proc结构体的指针

3)s_ttyvp是指向控制终端vnode结构的指针

4)s_ttyp是指向控制终端tty结构的指针

5)s_sid是会话id

 

tty结构体

1)t_session指向将此终端作为控制终端的session结构(注意,tty结构指向session结构,session结构也指向

   tty)。终端在市区载波信号时使用此指针将挂起信息发送给会话首进程

2)t_pgrp是指向前台进程组的pgrp结构。终端驱动程序用此字段将信号发送给前台进程组。

3)t_termios是包含所有这些特殊字符和与该终端有关信息(如波特率,回显打开或关闭)的结构

4)t_winsize是包含终端窗口当前大小的winsize型结构。当终端窗口大小改变时,信号SIGWINCH被发送至前台

   进程组。

 

pgrp结构体(包含一个特定进程组的信息)

1)pg_id是进程组ID

2)pg_session指向此进程组所属会话的session结构

3)pg_members是指向此进程组proc结构表的指针,该proc结构代表进程组的成员

 

proc结构体

1)p_pid包含进程ID

2)p_pptr是指向父进程proc结构的指针

3)p_pglist是一个结构,其中包含两个指针,分别指向进程组中上一个和下一个进程

最后还有一个vnode结构,在打开控制终端设备时分配此结构体,进程对/dev/tty的所有访问都通过vnode。

 

 

 

 

 

 

 


UNIX环境高级编程 进程关系




推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
author-avatar
PHP白姐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有