进程标识pid
id=0的是调度进程(swapper),该进程是内核的一部分,并不执行磁盘的任何的程序,也被称为系统进程
id=1 是init进程,属于用户态进程,但是以超级用户特权运行,是所有孤儿进程的父进程
#include <unistd.h>
pid_t getpid(void);
Returns: process ID of calling process
pid_t getppid(void);
Returns: parent process ID of calling process
uid_t getuid(void);
Returns: real user ID of calling process
uid_t geteuid(void);
Returns: effective user ID of calling process
gid_t getgid(void);
Returns: real group ID of calling process
gid_t getegid(void);
Returns: effective group ID of calling process
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
Both return: 0 if OK, −1 on error
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
Both return: 0 if OK, −1 on error
fork
#include <unistd.h>
pid_t fork(void);
Returns: 0 in child, process ID of child in parent, −1 on error
fork函数调用一次,返回两次,其中返回0是child进程,pid>0则是子进程的pid.内核一般保存父进程的区域堆栈,数据段的完全副本,且副本的访问权限只读,父进程或者子进程试图修改的话,内核就会建立修改区域的副本,(Copyy-On-Write)
wait and waitpid
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
/* Wait for a child to die. When one does, put its status in *STAT_LOC
and return its process ID. For errors, return (pid_t) -1.This function is a cancellation point and therefore not marked with
__THROW. */
extern __pid_t wait (int *__stat_loc);
void tl::testProcess(){
auto preStatus = [](int status)->void {
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n",
WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core file generated)" : "");
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number = %d\n",
WSTOPSIG(status));
};
pid_t pid;
int status;
if ((pid = fork()) < 0) {
err_sys("fork error");
}
else if (pid == 0) /* child */
exit(7);
if (wait(&status) != pid) /* wait for child */
err_sys("wait error");
preStatus(status); /* and print its status */
if ((pid = fork()) < 0) {
err_sys("fork error");
}
else if (pid == 0) /* child */
abort(); /* generates SIGABRT */
if (wait(&status) != pid) /* wait for child */
err_sys("wait error");
preStatus(status); /* and print its status */
if ((pid = fork()) < 0) {
err_sys("fork error");
}
else if (pid == 0) /* child */
status /= 0; /* divide by 0 generates SIGFPE */
if (wait(&status) != pid) /* wait for child */
err_sys("wait error");
preStatus(status); /* and print its status */
exit(0);
}
result:
└─$ ./tl.out
normal termination, exit status = 7
abnormal termination, signal number = 6
abnormal termination, signal number = 8
exec
该函数会创建一个进程,该进程完全取代原来的进程,从新进程的main开始执行
#include <unistd.h>
int execl(const char *pathname, const char arg0, … / (char *)0 */ );
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char arg0, …
/ (char *)0, char *const envp[] */ );
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char arg0, … / (char *)0 */ );
int execvp(const char *filename, char *const argv[]);
int fexecve(int fd, char *const argv[], char *const envp[]);
All seven return: −1 on error, no return on success
#include "log/logx.h"
#include <error.h>
#include<sys/wait.h>
#include <sys/resource.h>
#include <string.h>
void test();
int main() {
test();
}
void test() {
if (execl("/usr/bin/cal", "cal",nullptr) < 0) {
LOGXF("error", strerror(errno));
}
else LOGXA("start succeed");//this will not run ,because execl will use this process
}
/*
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$ sudo ./TestLinux.out
April 2022
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
*/
用户标识
char *getlogin(void);
char *getuid(void);
#include "log/logx.h"
#include <error.h>
#include<sys/wait.h>
void test();
int main() {
test();
}
void test() {
LOGXA(VAR_DATA(getlogin()));
LOGXA(VAR_DATA(getuid()));
}
进程调度
int nice(int incr);
Returns: new nice value − NZERO if OK, −1 on error
只会影响自己的值,不会影响其他进程的,incr越小优先级越大,系统会自动调整到合适的值
#include <sys/resource.h>
int getpriority(int which, id_t who);
Returns: nice value between −NZERO and NZERO−1 if OK, −1 on error
#include <sys/resource.h>
int setpriority(int which, id_t who, int value);
Returns: 0 if OK, −1 on error
#include "log/logx.h"
#include <error.h>
#include<sys/wait.h>
#include <sys/resource.h>
void test();
int main() {
test();
}
void test() {
int result = nice(20);
LOGXA(VAR_DATA(result));
result = getpriority(PRIO_PROCESS, 0);
LOGXA(VAR_DATA(result));
result= setpriority(PRIO_PROCESS, 0, 25);
LOGXA(VAR_DATA(result));
result = getpriority(PRIO_PROCESS, 0);
LOGXA(VAR_DATA(result));
}
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$ ./TestLinux.out
[+] log construction, can use it /home/kali/projects/TestLinux/bin/x64/Debug/_log/log.html
[0]09:01:18[info][140028126343552] [test] result: 19 (test_main.cpp:14)
[1]09:01:18[info][140028126343552] [test] result: 19 (test_main.cpp:16)
[2]09:01:18[info][140028126343552] [test] result: 0 (test_main.cpp:18)
[3]09:01:18[info][140028126343552] [test] result: 19 (test_main.cpp:20)
[+] ~log deconstruction
进程关系
进程组
pid_t getpgrp(void); //获取进程组的gid
#include "log/logx.h"
#include <error.h>
#include<sys/wait.h>
#include <sys/resource.h>
void test();
int main() {
test();
}
void test() {
while (true){
LOGXD(getpgrp());
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
/*
┌──(kali㉿kali)-[~]
└─$ /home/kali/projects/TestLinux/bin/x64/Debug/TestLinux.out
[+] log construction, can use it /home/kali/_log/log.html
[0]06:13:12[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[1]06:13:13[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[2]06:13:14[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[3]06:13:15[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[4]06:13:16[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[5]06:13:17[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[6]06:13:18[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[7]06:13:19[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[8]06:13:20[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[9]06:13:21[debg][140493772470080] [test] 138810 (test_main.cpp:16)
[10]06:13:22[debg][140493772470080] [test] 138810 (test_main.cpp:16)
root 138715 0.0 0.0 0 0 ? I 06:10 0:00 [kworker/u64:2-events_unbound]
kali 138810 0.0 0.0 6028 1824 pts/3 S+ 06:13 0:00 /home/kali/projects/TestLinux/bin/x64/Debug/TestLinux.out
kali 138812 0.0 0.1 9800 3628 pts/0 R+ 06:13 0:00 ps -aux
*/
pid_t getpgid(pid_t pid);
getpgid(0) == getpgrp()
int setpgid(pid_t pid, pid_t pgid);
#include "log/logx.h"
#include <error.h>
#include<sys/wait.h>
#include <sys/resource.h>
void test();
int main() {
test();
}
void test() {
while (true){
LOGXD(VAR_DATA(getpgid(0)),VAR_DATA(getpgrp()),VAR_DATA(getpgid(139656)));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
/*
└─$ /home/kali/projects/TestLinux/bin/x64/Debug/TestLinux.out 130 ⨯
[+] log construction, can use it /home/kali/_log/log.html
[0]06:48:56[debg][140477147711296] [test] getpgid(0): 139942 getpgrp(): 139942 getpgid(139656): 139641 (test_main.cpp:13)
[1]06:48:57[debg][140477147711296] [test] getpgid(0): 139942 getpgrp(): 139942 getpgid(139656): 139641 (test_main.cpp:13)
[2]06:48:58[debg][140477147711296] [test] getpgid(0): 139942 getpgrp(): 139942 getpgid(139656): 139641 (test_main.cpp:13)
[3]06:48:59[debg][140477147711296] [test] getpgid(0): 139942 getpgrp(): 139942 getpgid(139656): 139641 (test_main.cpp:13)
[4]06:49:00[debg][140477147711296] [test] getpgid(0): 139942 getpgrp(): 139942 getpgid(139656): 139641 (test_main.cpp:13)
*/
session
一个session由一个或多个进程组组成
pid_t setsid(void); 该进程如果不是进程组的组长,则会新建会话,如果该进程是组长了则返回错误,解决的办法是fork进程,然后子进程会有单独的pid
void test() {
if (setsid() == -1) {
auto pid=fork();
if (pid == 0) {
LOGXD("child", getpid());
LOGXD(VAR_DATA(setsid()));
LOGXD(VAR_DATA(getsid(getpgid(0))));
}
else {
LOGXD("parent", getpid());
}
}
}
/*
└─$ ./TestLinux.out
[+] log construction, can use it /home/kali/projects/TestLinux/bin/x64/Debug/_log/log.html
[+] log construction, can use it /home/kali/projects/TestLinux/bin/x64/Debug/_log/log.html
[0]07:12:43[debg][140152152371584] [test] child 140575 (test_main.cpp:15)
[0]07:12:43[debg][140152152371584] [test] parent 140574 (test_main.cpp:21)
[1]07:12:43[debg][140152152371584] [test] setsid(): 140575 (test_main.cpp:16)
[2]07:12:43[debg][140152152371584] [test] getsid(getpgid(0)): 140575 (test_main.cpp:17)
[+] ~log deconstruction
[+] ~log deconstruction
*/
controlling Terminal
会话会存在一个控制终端,让会话和控制终端联系的叫控制进程,每个控制终端将会话分成一个前台进程组和若干后台进程组
需要有一种方法来通知内核哪一个进程组是前台进程组,这样,终端设备驱动程序就能了解将终端输入和终端产生的信号送到何处。
#include <unistd.h>
pid_t tcgetpgrp(int filedes); //返回值:若成功则返回前台进程组的进程组ID,出错则返回-1.
int tcsetpgrp(int filedes, pid_t pgrpid); //返回值:成功则返回0,出错则返回-1.
void test() {
LOGXD("now_process_group_id:", VAR_DATA(getpgrp()));
LOGXD("pre_process_group_id:" VAR_DATA(tcgetpgrp(STDIN_FILENO)));
if (tcsetpgrp(STDIN_FILENO, getpgrp()) == 0) {
LOGXD("pre_process_group_id:" VAR_DATA(tcgetpgrp(STDIN_FILENO)));
}
else {
LOGXW("set fail");
}
}
/*
└─$ ./TestLinux.out
[+] log construction, can use it /home/kali/projects/TestLinux/bin/x64/Debug/_log/log.html
[0]07:41:27[debg][139648735146368] [test] now_process_group_id: getpgrp(): 141108 (test_main.cpp:12)
[1]07:41:27[debg][139648735146368] [test] pre_process_group_id:tcgetpgrp(0): 141108 (test_main.cpp:13)
[2]07:41:27[debg][139648735146368] [test] pre_process_group_id:tcgetpgrp(0): 141108 (test_main.cpp:15)
[+] ~log deconstruction
*/
job control
后台运行: xx &—(在后面加上&)
查看后台程序:jobs
将后台转入前台:fg %[后台序号]
/*
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$ ./TestLinux.out &
[1] 141243
[+] log construction, can use it /home/kali/projects/TestLinux/bin/x64/Debug/_log/log.html
[0]07:52:55[debg][140687585276288] [test] now_process_group_id: getpgrp(): 141243 (test_main.cpp:12)
[1]07:52:55[debg][140687585276288] [test] pre_process_group_id:tcgetpgrp(0): 137600 (test_main.cpp:13)
[1] + suspended (tty output) ./TestLinux.out
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$ jobs 1 ⚙
[1] + suspended (tty output) ./TestLinux.out
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$ fg %1 1 ⚙
[1] + continued ./TestLinux.out
[2]07:53:04[debg][140687585276288] [test] pre_process_group_id:tcgetpgrp(0): 141243 (test_main.cpp:15)
[+] ~log deconstruction
┌──(kali㉿kali)-[~/…/TestLinux/bin/x64/Debug]
└─$
*/
如果没有tcsetpgrp(STDIN_FILENO, getpgrp()) == 0这里,该程序是不会stop的,只因为设置了改进程是前台,但是他属于后台了,so
shell 执行程序
ps -o pid,ppid,pgid,sid,comm | cat1 | cat2
PID PPID PGID SID COMMAND
949 947 949 949 sh
1988 949 949 949 cat2
1989 1988 949 949 ps
1990 1988 949 949 cat1