3-6 SUID特权进程

SUID、SGID 概念 The Unix access rights flags setuid and setgid (short for “set user ID” and “set group ID”) allow users to run an executable with the file system permissions of the executable’s owner or group respectively and to change behaviour in directories. They are often used to allow users on a computer system to run programs with temporarily(暂时、临时) elevated(提高) privileges in order to perform a specific task. While the assumed user id or group id privileges provided are not always elevated, at a minimum they are specific. The flags setuid and setgid are needed for tasks that require different privileges than what the user is normally granted, such as the ability to alter system files or databases to change their login password. Some of the tasks that require additional privileges may not immediately be obvious, though, such as the ping command, which must send and listen for control packets on a network interface. ——setuid ...

2022-03-08 10:19:25 · 王二

3-5多进程编写

多进程编写需要清楚的几个问题 创建了几个进程? 每个进程 $count 是多少? 每个进程从哪个地方开始运行代码的? fork 之后,每个进程的变量 $i, $count 的值是多少 ? 每个进程运行到哪一行语句结束? 示例一: 代码 <?php $count = 10; for ($i = 0; $i < 2; $i++){ $pid = pcntl_fork(); // step1-1 parent 创建子进程 child-1: count = 10, i = 0 // step3-1 cpu 调度 parent 创建子进程 child-2: count = 100, i = 1 // step5-1 cpu 调度 child-1 创建子进程 child-3: count = 11, i = 1 if ($pid == 0){ $count += 1; // step1-2 child-1 执行:count = 11, i = 1 // step4 child-2 执行: count = 101, i = 2 // child-2 最终结果:count = 101 // step6 child-3 执行:count = 12, i = 2 } else { $count *= 10; // step2 cpu 调度 parent:count = 100, i = 1 // step3-2 cpu 调度 parent:count = 1000, i = 2 for循环退出 // parent 最终结果:count = 1000 // step5-2 cpu 调度 child-1:count = 110, i = 2 // child-1 最终结果:count = 110 } } while(1){ fprintf(STDOUT, "pid=%d,count=%d\n", posix_getpid(), $count); sleep(3); } 分析: step1-1 parent 创建子进程 child-1:count = 10, i = 0 step1-2 child-1 执行:count = 11, i = 1 step2 cpu 调度 parent:count = 100, i = 1 step3-1 cpu 调度 parent 创建子进程 child-2: count = 100, i = 1 step3-2 cpu 调度 parent:count = 1000, i = 2 for循环退出 parent 最终结果:count=1000 step4 child-2 执行: count = 101, i = 2 child-2 最终结果:count = 101 step5-1 cpu 调度 child-1 创建子进程 child-3: count = 11, i = 1 step5-2 cpu 调度 child-1:count = 110, i = 2 child-1 最终结果:count = 110 step6 child-3 执行:count = 12, i = 2 ...

2022-03-07 12:15:30 · 王二

3-4进程调度

pcntl_fork 创建了一个子进程,这个时候就会存在父进程和子进程,cpu先调度哪个进程? pcntl 封装了可以控制进程优先级的函数 pcntl_setpriority(setpriority),修改任意进程的优先级,pcntl_getpriority(getpriority)获取任意进程的优先级。 进程的观察命令:top top - 23:28:59 up 13:13, 1 user, load average: 0.30, 1.20, 1.61 任务: 386 total, 1 running, 385 sleeping, 0 stopped, 0 zombie %Cpu(s): 2.8 us, 1.7 sy, 0.1 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st MiB Mem : 5855.6 total, 664.6 free, 3875.4 used, 1315.7 buff/cache MiB Swap: 976.0 total, 364.7 free, 611.3 used. 1379.6 avail Mem 进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND 7305 wanger 20 0 4956504 454380 52432 S 4.6 7.6 28:24.62 gnome-shell ... 在 Linux 系统中,一般把进程/线程称为任务Task。 ...

2022-03-05 22:20:09 · 王二

3-3进程exec

pcntl_exec 函数用来执行一个程序,它内部的系统调用是 execve 一般的用法是父进程先创建一个子进程,然后子进程调用这个函数,正文段(代码段)+ 数据段会被新程序替换,它的一些属性会继承父进程,PID并没有发生变化。 execve() executes the program referred to by pathname. This causes the program that is currently being run by the calling process to be replaced with a new program, with newly initialized stack, heap, and (initialized and uninitialized) data segments. pathname must be either a binary executable, or a script starting with a line of the form: #!interpreter [optional-arg] ——execve 示例: demo7.php <?php function showID($str) { $pid = posix_getpid(); fprintf( STDOUT, "%s pid=%d,ppid=%d,gpid=%d,sid=%d,uid=%d,gid=%d\n", $str, $pid, posix_getppid(), posix_getpgrp(), posix_getsid($pid), posix_getuid(), posix_getgid() ); } showID("parent:"); $pid = pcntl_fork(); if (0 == $pid) { pcntl_exec('/usr/bin/php', ['demo2.php', 'a', 'b', 'c']); echo "hello world"; // 不会执行, } $exitPid = pcntl_wait($status); if ($exitPid > 0){ fprintf(STDOUT,"exit pid=%d\n",$exitPid); } demo2.php ...

2022-03-05 12:18:18 · 王二

3-2进程退出和回收

进程的退出 PHP 进程退出的几种情况 运行到最后一行语句 运行时遇到 return 运行时遇到 exit() 函数的时候 程序异常的时候 进程接收到中断信号 正常结束、异常结束(跟信号有关),不管以何种方式退出,都有一个终止状态码。 僵尸进程 僵尸进程(zombie process):指子进程已结束,但是父进程还没有使用 wait(pcntl_wait)/pcntl_waitpid(waitpid) 来回收。 进程结束时并不会真的退出,还会驻留在内存中,父进程需要通过 wait 「pcntl_wait」函数来获取进程的终止状态码,同时该函数会释放终止进程的内存空间。否则容易造成僵尸进程过多,占用大量内存空间。 wait 函数挂起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回。子进程使用的所有系统资源将被释放。关于 wait 在您系统上工作的详细规范请查看您系统的 wait(2)手册。 ——pcntl_wait 示例: <?php $pid = pcntl_fork(); if (0 === $pid) { fprintf(STDOUT, "我是子进程,pid = %d,运行完我就没事啦。\n", posix_getpid()); } else { fprintf(STDOUT, "我是父进程,pid = %d。\n", posix_getpid()); sleep(1); while (1) { # code... ; } } 运行结果: php demo5.php 我是父进程,pid = 1282。 我是子进程,pid = 1283,运行完我就没事啦。 进程状态: laradock@3a6c2da5a07b:/var/www$ ps exj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 807 1282 1282 807 pts/2 1282 R+ 1000 0:15 php demo5.php LC_ALL=en_US.UTF-8 NVM_DIR=/home/laradock/.nvm LS_COLORS=no=00:fi=00: 1282 1283 1282 807 pts/2 1282 Z+ 1000 0:00 [php] <defunct> // 僵尸进程 进程产生的文件 一个进程运行时,会在 /proc/PID 目录产生文件。 ...

2022-03-04 15:58:53 · 王二

3-1进程标识与fork

进程标识 一个程序被加载到内存中运行,系统会为这个进程分配相应的标识信息,比如 pid,ppid,uid,euid,pgid,sid,gid,egid… 进程查看命令 pstree 可看出进程间的关系 父子,兄弟; ps -exj ps -aux ps … PID PPID PGID UID TTY STAT TIME COMMAND laradock@3a6c2da5a07b:/var/www$ ps exj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 24 24 24 pts/1 495 Ss 1000 0:00 bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/larado 24 495 495 24 pts/1 495 R+ 1000 13:37 php demo4.php LC_ALL=en_US.UTF-8 NVM_DIR=/home/laradock/.nvm LS_COLORS=no=00:fi=00: 0 496 496 496 pts/2 1051 Ss 1000 0:00 bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/larado 496 1051 1051 496 pts/2 1051 R+ 1000 0:00 ps exj LC_ALL=en_US.UTF-8 NVM_DIR=/home/laradock/.nvm LS_COLORS=no=00:fi=00:di=01;3 进程状态码 D uninterruptible sleep (usually IO) I Idle kernel thread R running or runnable (on run queue) S interruptible sleep (waiting for an event to complete) T stopped by job control signal t stopped by debugger during the tracing W paging (not valid since the 2.6.xx kernel) X dead (should never be seen) Z defunct (“zombie”) process, terminated but not reaped by its parent 打印进程标识 fprintf(STDOUT, "pid=%d\n", posix_getpid()); // 进程自己的标识 PID fprintf(STDOUT, "ppid=%d\n", posix_getppid()); // 父进程的标识 PPID fprintf(STDOUT, "pgid=%d\n", posix_getpgrp()); // 进程组长标识 PGID fprintf(STDOUT, "sid=%d\n", posix_getsid(posix_getpid())); // 会话标识 SID fprintf(STDOUT, "uid=%d\n", posix_getuid()); // 用户标识 UID 当前登录用户,实际用户id fprintf(STDOUT, "gid=%d\n", posix_getgid()); // 组ID GID fprintf(STDOUT, "euid=%d\n", posix_geteuid()); // 有效用户id EUID fprintf(STDOUT, "egid=%d\n", posix_getegid()); // 有效组id EUID pid=506 ppid=37 pgid=506 sid=37 uid=1000 gid=1000 euid=1000 egid=1000 fork pcntl_fork ...

2022-02-28 17:02:33 · 王二

2-3解释器文件

解释器文件 解释器文件,是一种文本文件,例如 PHP 写的解释器文件 demo.php。 #!/usr/bin/php <?php echo 'Hello World!' chmod u+x demo.php 赋予可执行权限,即可直接以 ./demo.php 执行。 解释器,是可执行文件 ELF,例如 /usr/bin/php。 bash 进程启动过程 bash 进程是如何创建的? 直接在 centos、ubuntu等终端直接登录,由 login 服务开启 bash 进程。 通过网络方式登录到 shell 终端,由 sshd 服务开启 bash 进程。 sshd 服务默认监听 22 端口。 进程观察的几个命令: pstree 查看 Linux 进程间的关系,显示进程树。 pstree -ap: ├─sshd,9408 │ └─sshd,444836 │ └─bash,444875 │ └─pstree,444893 -ap ctrl+c 产生一个中断信号,退出当前终端正在执行的进程。 ctrl+z 把当前台进程丢到后台去暂停。 strace,跟踪系统调用和信号。 通过 strace -f -s 65500 -p 9408 -o ssh.log 追踪 pid = 9408 的 sshd 进程的系统调用,来分析 bash 进程是如何创建的。 strace: Process 9408 attached strace: Process 447115 attached ... strace: Process 447151 attached ^Cstrace: Process 9408 detached strace: Process 447115 detached strace: Process 447143 detached ssh.log 部分内容: 9408 select(95, [3], NULL, NULL, NULL) = 1 (in [3]) 9408 accept(3, {sa_family=AF_INET, sin_port=htons(4143), sin_addr=inet_addr("1xx.1x9.xx3.1xx")}, [128->16]) = 4 // accept 用来接收一个 socket 客户端连接 ... 9408 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1fc4482210) = 447115 // clone = fork 用来创建一个子进程 447115 execve("/usr/sbin/sshd", ["/usr/sbin/sshd", "-D", "-R"], 0x55d325ea09c0 /* 7 vars */) = 0 // execve 用来执行一个程序 447115 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD <unfinished ...> 447143 set_robust_list(0x7fa0e70b0220, 24 <unfinished ...> 447115 <... clone resumed>, child_tidptr=0x7fa0e70b0210) = 447143 447143 <... set_robust_list resumed>) = 0 // 创建子进程 447143 ... 447143 execve("/bin/bash", ["-bash"], 0x563bf3853680 /* 25 vars */) = 0 // 执行 bash 程序 a. 通过 accept 接收 ssh 客户端连接; b. 通过 clone 创建一个子进程; c. 通过 execve 执行 sshd 程序; d. 创建一个子进程; e. 执行 bash 程序。 ...

2022-02-18 20:41:06 · 王二

2-2命令行参数与环境参数表

命令行参数 php 两种请求方式: 浏览器请求过程: http://127.0.0.1/demo2.php 浏览器访问 —> tcp 协议请求 —> Apache/Nginx[集成环境]web服务器 —> php-fpm 服务 cli 请求: php demo2.php a b c d cli 是直接在终端调用 php 解释器。 其中 [a,b,c,d] 就叫命令行参数。 环境参数表 当前 bash 进程调用 execve 函数传递进来的参数。 print_r(getenv());

2022-02-17 20:19:26 · 王二

2-1程序与进程

什么是程序? ELF 概念 程序(Program) 一般是指可执行文件,在Linux系统中它按 ELF 格式进行存储,并没有后缀可标识其文件类型,需要通过 file 命令来查看 ELF 文件的具体类型。 ELF 全称是 Executable Linkable Format (可执行与可链接格式),在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的,也是Linux的主要可执行文件格式。 ELF文件种类: EXEC 可执行文件 object code 目标代码文件 shared libraries 共享库文件 REL 可重定位文件 在Linux中为 xx.o xx.a,也称为静态库文件,其中 xx.o 称为目标文件,可被链接器链接成为可执行文件,静态库文件,动态库文件。 示例:php扩展中常用的动态库文件如curl,网络框架库如event.so socket扩展库sockets.so c/c++项目程序员一般引用第三方的库函数都是使用第三方编译好的动态库或是静态库文件 .so, .a。 core dump 核心转储文件 存储进程产生的异常信息。是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写入一个磁盘文件。这种信息往往用于调试。 ELF 文件格式 ELF 文件信息是以 section 或 segment 来存储的。 每个 ELF 文件都由一个 ELF 首部和紧跟其后的文件数据部分组成。数据部分可以包含: 程序头表(Program header table):描述 0 个或多个内存段信息 分段头表(Section header table):描述 0 段或多段链接与重定位需要的数据 程序头表与分段头表引用的数据,比如 .text .data ...

2022-02-16 20:46:08 · 王二

1-1课程介绍

课程简介 本课程内容涵盖了 Linux 下 ELF 文件、进程、进程控制原语、进程调度算法、中断信号系统、Linux bash 进程与终端、进程、特权进程、守护进程、会话、进程间通信、UNIX域进程间通信、进程间同步、进程池等知识技术点。 课程测试环境 ubuntu 20.04 php 7.x VScode 课程需要有哪些基础知识 PHP使用1年以上 能独立编译安装PHP和相关扩展 对Linux基础命令有所了解 不浮躁有足够的耐心学习知识 会使用翻译工具,爱百度google的同学^_^ 大其心,容天下之物;虚其心,受天下之善;平其心,论天下之事;潜其心,观天下之理;定其心,应天下之变。 ——— 《呻吟语·卷二·乐集·修身》 如今新兴语言层出不穷,我还有必要学PHP? 本套课程集中于 Linux 下多进程编程知识,虽然使用 PHP 来演示讲课,但在讲解中,会涉及到内核系统调用函数的说明,因为Linux内核系统调用对于所有的编程语言都是通用的。也就是说大家换一门其它编程语言,在本套课程所学到的知识都能完全应用到其它语言中,除非大家换了Linux操作系统,或是Linux操作系统的实现不使用C语言了。这也是本套课程的目标。让大家掌握方法以便能深入的研究 Linux 的 API(C 语言定义好的接口函数)。 go,python,nodejs,java,php rust,… 不论应用使用何种编程语言,底层的系统调用函数完全一致。 例如 PHP 的 pcntl_fork 底层调用的系统函数:fork,clone 课程适合哪些人? 以下列出几点小问题如果您感兴趣,则本套课程将非常适合您! PHP 解释器是什么类型的文件?我怎么查看它?为什么我在终端执行 php index.php 它就执行了?从哪里开始执行的?到哪儿结束呢? elf 文件; 通过 file /usr/bin/php 查看; /www/server/php/80/bin/php: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5e0ab6a4e4cdb7a1da44a13c30661ecc8d7af995, for GNU/Linux 3.2.0, with debug_info, not stripped 我通过终端如 ssh 等连接我的阿里云 Linux centos8 时,系统做了什么?我在它的终端下输入 php index.php 或是其它命令时它干啥了? 为什么我在 index.php 文件中打印 $argv 参数时能打印出东西? 如果我启动 php index.php 之后,我退出终端时它是不是退出了?为什么?如果不想让它退出怎么办呢?为什么? 退出了; 父进程结束,子进程也结束了; 守护进程,后台运行。 僵尸进程是怎么产生的?对系统会有什么影响呢?我要怎么处理掉呢?我又如何查看呢?还有孤儿进程又是怎么产生的呢?它的父亲又是谁呢? 我启动 php index.php 之后,它的内存数据在哪里我可以查看呢?为什么要查看呢? 我启动 php index.php 之后,它调用系统哪些函数呢?我怎么查看呢?查到之后,我又如何知道这些系统函数是做什么的呢?其它编程语言如 Java,go 运行之后我又如何查看它内部调用哪些系统函数了呢?和 PHP 又有啥关系呢? 什么是控制终端,终端是干嘛的呢?跟我启动的 php index.php 进程有关系???还很大??? 我启动多个进程以后,它们是啥关系呢?我要怎么控制每个进程呢? 程序启动之后,它的内存代码和数据段我在创建新进程的时候它是怎么复制的呢?为啥要复制呢? 我编写 Java 一个小程序,然后我 javac xxx 或是 go run xxx 它就运行了和 php index.php 一样吗【内部调用】??? 一样 如果我想自己写一套多进程的服务器小项目,要运用到哪些知识点呢? socket?tcp/ip?第一关多进程,实现跨进程间任务投递我要怎么实现呢?客户请求过来后,我要立马处理吗?我想自己动手搞一套网络通信框架要不要先搞清楚以上的问题呢? 我换语言了学完还能有用??? 么问题。 ...

2022-02-15 21:30:12 · 王二