diff --git a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md index f22b763..d38c883 100644 --- a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md +++ b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md @@ -968,4 +968,142 @@ struct rlimit { rlim_t rlim_cur; /* soft limit */ rlim_t rlim_max; /* hard limit */ }; -``` \ No newline at end of file +``` + + +# 进程基本知识 + +已经进入**多进程**阶段 + +## 进程标识符`pid` +类型`pid_t`,传统意义上是一个16位有符号整型数。 +命令`ps` +常用命令:`ps axf`,`ps aux`,`ps axm`,`ps ax -L` +进程号是顺次向下使用 +```c +// 返回当前进程号 +pid_t getpid(void); + +// 返回父进程的进程号 +pid_t getppid(void); +``` + +## 进程的产生 + +`pid_t fork();` +- 以**复制(duplicating)**当前进程的方式创建一个新进程 +- 和`setjmp`一样,执行一次,返回两次 +- 在`fork`处复制,不会从头运行 + +`fork`后父子进程的不同之处: +1. `fork`的返回值不一样 +2. `pid`不同 +3. `ppid`也不同 +4. 未决信号和文件锁不继承 +5. 资源利用量清0 + +`init`进程:**1号**,是所有进程的祖先进程 + +调度器的调度策略来决定哪个进程先执行 + +`fflush()`的重要性 + +```c +/* + * vfork创建的子进程只能做exec或者exit + * ! 基本废弃 + */ +pid_t vfork(void); +``` + +## 进程的消亡及释放资源 +```c +// 等待进程状态发生变化 +pid_t wait(int *status); // 阻塞 + +pid_t waitpid(pid_t pid, int *status, int options); + +int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); + + +wait3(); +wait4(); +``` + +分配法和交叉分配法,90%优先选择交叉分配法。 + +池类算法: +上游往池子里放任务,下游三个线程从池子里取任务。 + +## `exec`函数族 +eg. `bash`进程创建`primer`进程 + +```c +// exec函数族:替换当前进程的映像 + +extern char **environ; + +int execl(const char *path, const char *arg, ...); + +int execlp(const char *file, const char *arg, ...); + +int execle(const char *path, const char *arg, ..., char * const envp[]); + +int execv(const char *path, char *const argv[]); + +int execvp(const char *file, char *const argv[]); + +``` + +## 用户权限及组权限 + + +## 观摩课:解释器文件 + + +## `system()`函数 + + +## 进程会计 + + +## 进程时间 + + +## 守护进程 + + +## 系统日志 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/C13-Linux系统编程/process_basic/ex.c b/C13-Linux系统编程/process_basic/ex.c new file mode 100644 index 0000000..6d85cdd --- /dev/null +++ b/C13-Linux系统编程/process_basic/ex.c @@ -0,0 +1,28 @@ +#include +#include +#include + +/** + * @brief data +%s + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + puts("Begin!"); + fflush(NULL); // !!! + + execl("/bin/date", "date", "+%s", NULL); + // NULL 作为参数列表的结束标志 + + // !! 如果不出错,不会到这里 + perror("execl()"); + exit(1); + + puts("End!"); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/few.c b/C13-Linux系统编程/process_basic/few.c new file mode 100644 index 0000000..f1a6c38 --- /dev/null +++ b/C13-Linux系统编程/process_basic/few.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +/** + * @brief few: folk, execl, wait + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + pid_t pid; + + puts("Begin!"); + + fflush(NULL); + + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); + } + + if (0 == pid) // child + { + execl("/bin/date", "date", "+%s", NULL); + perror("execl()"); + exit(1); + } + + wait(NULL); + + puts("End!"); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/fork1.c b/C13-Linux系统编程/process_basic/fork1.c new file mode 100644 index 0000000..5b06406 --- /dev/null +++ b/C13-Linux系统编程/process_basic/fork1.c @@ -0,0 +1,40 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + pid_t pid; + + /* + * 如果 ./fork1 > /tmp/out + * begin会由父进程输出两次 + * 缓冲问题 + * 文件时全缓冲 + */ + printf("[%d]Begin!\n", getpid()); + + fflush(NULL); // !!! 在fork之前刷新该刷新的流 + + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); + } + + if (pid == 0) // child + { + printf("[%d]Child is working!\n", getpid()); + } + else // parent + { + printf("[%d]Parent is working!\n", getpid()); + } + + printf("[%d]End!\n", getpid()); + + // getchar(); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/myshell.c b/C13-Linux系统编程/process_basic/myshell.c new file mode 100644 index 0000000..87a79fb --- /dev/null +++ b/C13-Linux系统编程/process_basic/myshell.c @@ -0,0 +1,41 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + while (1) + { + prompt(); + + getline(); + + parse(); + + if (内部命令) + { + ; + } + else // 外部命令 + { + fork(); + if (< 0) + { + ; + } + + if (0 ==) // child + { + execXX; + perror(); + exit(1); + } + else // parent + { + wait(); + } + } + } + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/primer0.c b/C13-Linux系统编程/process_basic/primer0.c new file mode 100644 index 0000000..98c9638 --- /dev/null +++ b/C13-Linux系统编程/process_basic/primer0.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#define LEFT 30000000 +#define RIGHT 30000200 + +/** + * @brief 求质数(单机版) + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + int i, j, mark; + + for (i = LEFT; i <= RIGHT; i++) + { + mark = 1; + for (j = 2; j < i / 2; j++) + { + if (i % j == 0) + { + mark = 0; + break; + } + } + + if (mark) + printf("%d is a primer\n", i); + } + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/primer1.c b/C13-Linux系统编程/process_basic/primer1.c new file mode 100644 index 0000000..a8c67b2 --- /dev/null +++ b/C13-Linux系统编程/process_basic/primer1.c @@ -0,0 +1,53 @@ +#include +#include +#include + +#define LEFT 30000000 +#define RIGHT 30000200 + +/** + * @brief 求质数(多进程版) + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + int i, j, mark; + pid_t pid; + + for (i = LEFT; i <= RIGHT; i++) + { + + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); + } + + if (pid == 0) // child + { + mark = 1; + for (j = 2; j < i / 2; j++) + { + if (i % j == 0) + { + mark = 0; + break; + } + } + if (mark) + printf("%d is a primer\n", i); + + sleep(1000); // * 让父进程先结束 + exit(0); // ! 退出子进程 + // ! init 在孤儿进程 exit 后才收尸 + } + } + + // sleep(1000); // * 让子进程先结束,子进程会变成僵尸态 + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/primer2.c b/C13-Linux系统编程/process_basic/primer2.c new file mode 100644 index 0000000..c256900 --- /dev/null +++ b/C13-Linux系统编程/process_basic/primer2.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +#define LEFT 30000000 +#define RIGHT 30000200 + +/** + * @brief 求质数(多进程版) + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + int i, j, mark; + pid_t pid; + + for (i = LEFT; i <= RIGHT; i++) + { + + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); + } + + if (pid == 0) // child + { + mark = 1; + for (j = 2; j < i / 2; j++) + { + if (i % j == 0) + { + mark = 0; + break; + } + } + if (mark) + printf("%d is a primer\n", i); + + exit(0); // ! 退出子进程 + } + } + + // int st; + for (i = LEFT; i <= RIGHT; i++) + // wait(&st); + wait(NULL); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/primerN.c b/C13-Linux系统编程/process_basic/primerN.c new file mode 100644 index 0000000..e8b72b4 --- /dev/null +++ b/C13-Linux系统编程/process_basic/primerN.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +#define LEFT 30000000 +#define RIGHT 30000200 +#define N 3 + + +/** + * @brief 求质数(多进程版) + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + int i, j, n, mark; + pid_t pid; + + for (n = 0; n < N; n++) + { + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); // ! 加入在第三次fork失败时,退出,前两次没有收尸 + } + + if (pid == 0) + { + for (i = LEFT + n; i <= RIGHT; i += N) + { + + mark = 1; + for (j = 2; j < i / 2; j++) + { + if (i % j == 0) + { + mark = 0; + break; + } + } + if (mark) + printf("[%d]%d is a primer\n", n, i); + } + + exit(0); // ! 退出子进程 + } + } + + for (n = 0; n < N; n++) + wait(NULL); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/process_basic/sleep.c b/C13-Linux系统编程/process_basic/sleep.c new file mode 100644 index 0000000..754a333 --- /dev/null +++ b/C13-Linux系统编程/process_basic/sleep.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +/** + * @brief few: folk, execl, wait + * @details + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + pid_t pid; + + puts("Begin!"); + + fflush(NULL); + + pid = fork(); + if (pid < 0) + { + perror("fork()"); + exit(1); + } + + if (0 == pid) // child + { + // execl("/bin/sleep", "sleep", "100", NULL); + execl("/bin/sleep", "httpd", "100", NULL); + // ! 低级木马:进程树里看到的是httpd 100 + + perror("execl()"); + exit(1); + } + + wait(NULL); + + puts("End!"); + + exit(0); +} \ No newline at end of file