Unix环境高级编程
1.acct 是一个工具包,里面包含有针对用户连接时间、进程执行情况等进行统计的工具。它可以记录用户登录信息。用户所执行的程序,程序执行情况信息等。acct 包含以下工具包命令,
ac #显示登录账号的简要信息
accton #打开或关闭进程记录功能
last #显示曾经登录过的用户
lastcomm #显示已执行过的命令
sa #进程用户记录信息的摘要
dump-utmp #输出utmp文件内容
dump-acct #输出acct或pacct文件内容
参考https://blog.51cto.com/mingongge/5109376
第9章:进程关系
1.同一进程组中的各进程接收来自同一终端的各种信号,每个进程组有一个组长进程
2.从进程组创建开始到其中最后一个进程离开为止的时间区间称为进程组的生命期
3.进程组的最后一个进程可以终止,也可以转移到另一个进程组
4.一个进程只能为它自己或它的子进程设置进程组ID
5.会话是一个或多个进程组的集合。
6.非组长进程,调用setid()函数可以创建一个新会话,组长进程调用此函数返回出错
7.一个会话可以有一个控制终端,也可以没有。
8.会议首进程与控制终端建立会话连接,它叫控制进程
9.一个会话有一个前台进程组、几个后台进程组
10.中断键(delete或Ctrl+C)、中断信号(ctl+\),中断信号发送至前台进程组
11.网络断开,挂断信号发送到控制进程(会话首进程)
12.输入、输出重定向了,程序也能与控制终端交互,方法是open文件/dev/tty
13. cat << 0是输入重定向的其中一种写法。0可以换成使用字符串,表示分界符
1.在前台运行的进程用Ctl+Z将进程可以挂起(也就是暂停,进程收到的是SIGTSTP信号),用fg命令对业务放回前台运行时,这个进程会收到SIGCONT信号,程序继续前台运行
2.ps -o pid,ppid,pgid,tpgid,sid,comm 其中tpgid是打印这个进程所有会话的前台进程组id
第10章:信号
3.POSIX.1要求向新孤儿进程组中处于停止状态的每一个进程发送一挂断信号(SIGHUP),接着又向其发送继续信号(SIGCONT)
4.挂断信号(SIGHUP)的默认动作是终止进程
1. SIGTTIN信号,当一个后台进程组进程试图读其控制终端时,终端驱动程序产生信号,下列情形下不产生此信号,a)读进程忽略或阻塞此信号,b)读进程所属的进程组是孤儿进程组,此时读操作返回出错,errno设置为EIO
2. SIGTTOU信号,当一个后台进程组进程试图写其控制终端时,终端驱动程序产生信号
3. SIGWINCH信号,终端窗口大小发生变化,用ioctl可以得到或设置窗口大小,设置后内核将SIGWINCH信号发送至前台进程组
1.调用exec,新进程忽略之前进程设置为捕捉的信号 都将改为默认动作
2.if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, sig_int);
这句话的意思是"仅当SIGINT当前未被忽略时,进程才会捕捉它"
由上面这个写法中不难看出signal()的限制:不改变信号的处理方式就不能确定信号的当前处理方式。
而用sigaction()就可以"不改变信号的处理方式也能确定信号的当前处理方式"
3.fork()后的子进程继承父进程的信号处理方式
1.alarm()和pause()配和可以用来实现sleep()
2.alarm()的另一个用途是用于对可能阻塞的操作设置时间上限值
3.kill(pid, signo)可以将信号发送给进程或进程组
pid>0 信号发送给进程pid
pid=0 信号发送给自己进程组内所有进程
pid<0 信号发送给"组ID==|pid|"的进程组内所有进程
pid=-1 信号发给"发送进程有权限向他们发送信号的所有进程"
信号发送给其他进程需要权限:
超级用户可将信号发送给任一进程。
非超级用户规则是:发送者的实际用户ID(或有效用户ID) == 接收者的实际用户ID(或有效用户ID)
signo为0表示空信号,kill(xxx, 0)仍执行正常的错误检查,但不发送信号。这常被用来检查一个进程是否存在,不存在则kill()返回-1,
返回0也不一定表示你想要检查的那个进程存在哦,因为进程ID释放后可能分配给了其他进程
4.当一个信号产生时,内核通常在进程表中以某种形式设置一个标志。信号采取了这种动作时,内核向进程递送了一个信号。
在信号产生和信号递送的时间间隔内,称信号是未决的
5.信号递送给进程之前仍可改变对该信号的处理动作。sigpending()可判定哪些信号是设置为阻塞并处于未决状态。
6.进程解除对某个信号的阻塞之前,信号发生了多次,如果递送多次,称这种信号进行了排队。
7.sigprocmask()可检测和更改当前信号屏蔽字,每个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集。
1.sigprocmask()是仅为单线程进程定义的。处理多线程进程中信号的屏蔽使用另一个函数。
2.信号集sigset_t数据类型,待处理的信号个数超过31个,使用此数据类型。
有5个函数可以处理这个类型。sigemptyset()sigfillset()sigaddset()sigdelset()sigismember()
0) 向一个进程发送信号的4种写法
0.1) kill -9 1234
0.2) kill -KILL 1234 // 给进程发送特定信号 // -KILL只需要写SIGKILL 的后几个字母
0.3) kill -n 9 1234
0.4) kill -s SIGKILL 1234
0.5)kill -l // 列出所有信号值和名称
0.6) kill -l 9 // 查询信号9对应的名称
1.已经用signal()注册了一个信号的自定义处理方式,是否可以做到信号发生时,不立即执行"自定义处理方式",而是之后某个条件达到后再执行呢?
答案是可以的,用sigprocmask(SIG_BLOCK, xx, xx)将你关注的信号设置为阻塞,等某个条件达到后再将这个信号设置为非阻塞即可。
阻塞的意思就是内核不立即将此信号递送至进程。
2.sigaction()和signal()功能类似,功能更强大,
sigaction(mysigno, newaction, oldact);
newaction是一个结构体包含四个字段(handle, mask, flags, handle2)
1)mask 可以设置执行自定义处理方式过程中,阻塞哪些信号。
2)mysigno信号处理动作执行过程中,内核将阻塞mysigno。
2.1)flags 设置为SA_NODEFER, 则内核将不会阻塞mysigno
2.2)flags 设置为SA_RESETHAND, 当调用信号处理函数时,将信号的处理函数重置为缺省值
2.3)如果mysigno是SIGCHLD,且flags设置为NOCLDWAIT,则子进程退出后不会成为僵尸进程(调用进程仍会收到SIGCHLD信号---因为子进程终止了)
2.4)如果mysigno是SIGCHLD,且flags设置为NOCLDTSTP,则子进程停止(作业控制)时,调用进程不会收到SIGCHLD信号
2.5)如果mysigno是SIGCHLD,子进程终止时,父进程一定会收到SIGCHLD信号,无论flags是否设置为NOCLDWAIT或NOCLDTSTP
3)handle2比handle多两个参数, flags 设置为 SA_SIGINFO时, 使用handle2来处理。否则使用handle来处理