文章目录
进程
概念
进程是程序执行的过程,进程是系统分配资源的最小单位,由操作系统统一调度。
程序是静态的,进程是动态的,包括创建、调度、消亡。
并发与并行
并发:宏观并行,微观串行(CPU轮流使用)
并行:宏观和微观都是并行(CPU独立占用)
Linux进程管理
采用树形结构,为每个进程分配一个ID,ID作为当前进程的唯一标识,进程结束则收回。
进程ID和父进程ID分别通过getpid() 和 getppid() 函数来获取
getpid
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
//pid_t getpid(void);
//pid_t getppid(void);
int main(){
pid_t pid = getpid();
pid_t ppid = getppid();
printf("the programmer id is : %d\n",pid);
printf("the programmer father id is : %d\n",ppid);
return 0;
}
进程地址空间
进程的状态
进程相关命令
ps
显示当前进程
菜鸟教程
top
pstree
kill
创建进程
fork函数
fork函数会创建一个新的进程,调用fork函数的进程为父进程,产生的新进程为子进程
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回值:返回给父进程的是子进程pid,返回给子进程0,失败返回-1,并设置errno
子进程执行的代码和父进程调用fork之后的代码一致,父进程先执行fork后的代码,子进程后执行一遍。
父子进程的执行顺序由操作系统的调度算法决定。
子进程会拷贝父进程的地址空间的数据(copy or write)。
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
// pid_t fork(void);
int main(){
pid_t cpid;
printf("fork 之前:\n");
cpid = fork();
if(cpid == -1){
perror("[ERROR] fork():");
}
printf("fork 之后\n");
printf("get pid: %d \n",getpid());
printf("Hello World .\n");
return 0;
}
结果
fork 之前:
fork 之后
get pid: 35548
fork 之后
Hello World .
get pid: 35549
Hello World .
父子进程执行不同任务
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void){
pid_t cpid;
cpid = fork();
if(cpid == -1){
perror("[ERROR] fork : \n");
}
else if(cpid == 0){
printf("Child process task. \n");//子进程中执行
}
else if(cpid > 0){
printf("Parent process task.\n");//父进程中执
}
printf("Parent and Child process task.\n");// 父子进程一起执行
return 0;
}
结果
root@wangjudealy:/learn# ./a.out
Parent process task.
Parent and Child process task.
Child process task.
Parent and Child process task.
最好由父进程统一创建管理子进程
创建多个子进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
pid_t cpid;
cpid = fork();
if(cpid == -1){
perror("[ERROR] fork : \n");
exit(EXIT_SUCCESS);
}
else if(cpid == 0){
printf("Child A process task. pid is < %d > \n",getpid());//子进程A
printf("Parent process is < %d >\n",getppid());
printf("=====================================");
sleep(2);
exit(EXIT_SUCCESS);
}
else if(cpid > 0){
cpid = fork();
if(cpid == -1){
perror("[ERROR] fork : \n");
exit(EXIT_SUCCESS);
}
else if(cpid == 0){
printf("Child B process task. pid is < %d > \n",getpid());//子进程B
printf("Parent process is < %d >\n",getppid());
printf("=====================================");
sleep(2);
exit(EXIT_SUCCESS);
}
else if(cpid > 0){
cpid = fork();
if(cpid == -1){
perror("[ERROR] fork : \n");
exit(EXIT_SUCCESS);
}
else if(cpid == 0){
printf("Child C process task. pid is < %d > \n",getpid());//子进程C
printf("Parent process is < %d >\n",getppid());
printf("=====================================");
sleep(2);
exit(EXIT_SUCCESS);
}
}
}
printf("Parent and Child process task.\n");// 父子进程一起执行
return 0;
}
结果
root@wangjudealy:/learn# ./a.out
Child A process task. pid is < 35749 >
A Parent process is < 35748 >
=====================================
Parent and Child process task.
Child C process task. pid is < 35751 >
root@wangjudealy:/learn
Child B process task. pid is < 35750 >
B Parent process is < 1 >
=====================================
C Parent process is < 1 >
=====================================
进程的退出
进程退出时操作系统回收进程地址空间,并清理相关的数据结构
exit函数
终止进程,并刷新缓冲区
#include <stdlib.h>
void exit(int status);
_exit函数
exit底层调用 _exit,_exit终止进程不刷新缓冲区。
#include <unistd.h>
void _exit(int status);
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
// void exit(int status);
// pid_t fork(void);
int main(void){
pid_t cpid;
cpid = fork();
//创建子进程
if(cpid == -1){
printf("进程创建失败!!!\n");
exit(EXIT_FAILURE);
}
else if(cpid == 0){
printf("子进程 A 创建成功 进程号 < %d > ",getpid());
exit(EXIT_SUCCESS);
}
else if(cpid > 0){
cpid = fork();
if(cpid == -1){
printf("创建进程 B 失败\n");
_exit(EXIT_FAILURE);
}
else if(cpid == 0){
printf("子进程 B 创建成功 进程号 < %d >",getpid());
_exit(EXIT_SUCCESS);
}
}
return 0;
}
结果,只有A进程中的语句被打印,(printf是带有缓冲区的,exit退出时刷新缓冲区)
root@wangjudealy:/learn# 子进程 A 创建成功 进程号 < 36858 >
进程的等待
子进程运行结束后,进去僵死状态,并释放资源子进程在内核中的数据结构依然保留
父进程调用wait() ,与 waitpid() 函数等待子进程退出后,释放子进程遗留的资源
wait与waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
wstatus 该指针保存子进程退出状态值,获取具体值要使用 WEXITSTATUS() 宏定义
成功返回子进程pid,失败返回-1
wait调用后会阻塞调用进程,收回僵死状态的子进程的资源后返回。
pid_t waitpid(pid_t pid, int *wstatus, int options); pid = -1 :等待任意进程退出 pid > 0 : 等待特定进程退出 option:是否阻塞
进程替换
创建进程后,pid以及在内核中的信息保持不变,但所执行的代码进行替换
作用:通过一个进程启动另一个进程
应用:程序启动器,在一个程序里调用另一个应用的功能
exec函数族
#include <unistd.h>
extern char **environ;
int execl(const char *pathname, const char arg, …
/ (char *) NULL */);
int execlp(const char *file, const char arg, …
/ (char *) NULL */);
int execle(const char *pathname, const char arg, …
/, (char *) NULL, char *const envp[ ] */);
int execv(const char *pathname, char *const argv[ ]);
int execvp(const char *file, char *const argv[ ]);
int execvpe(const char *file, char *const argv[ ],
char *const envp[ ]);
通过execl函数执行 ls -l
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
// int execl(const char *pathname, const char *arg, ...
// /* (char *) NULL */);
int main(void){
int ret;
ret = execl("/bin/ls","ls","-l",NULL); //调用ls -l
if(ret == -1){
perror("[ERROR] excel():");
exit(EXIT_FAILURE);
}
return 0;
}
root@wangjudealy:/learn# ./a.out
total 100
-rw-r--r-- 1 root root 229 Mar 10 20:54 0310.c
-rw-r--r-- 1 root root 365 Mar 13 23:04 0313.c
-rw-r--r-- 1 root root 334 Mar 14 23:33 0314.c
-rw-r--r-- 1 root root 568 Mar 17 17:31 0317.c
-rw-r--r-- 1 root root 189 Mar 19 22:56 0319.c
-rw-r--r-- 1 root root 282 Mar 27 00:01 0326.c
-rw-r--r-- 1 root root 1252 Mar 28 10:22 032801.c
-rw-r--r-- 1 root root 658 Mar 28 21:03 032802.c
-rw-r--r-- 1 root root 379 Mar 28 21:48 032803.c
-rw-r--r-- 1 root root 314 Mar 28 09:48 0328.c
-rwxr-xr-x 1 root root 16784 Mar 28 21:48 a.out
drwxr-xr-x 2 root root 4096 Mar 17 22:18 day05
drwxr-xr-x 2 root root 4096 Mar 24 23:29 day08
-rw-r--r-- 1 root root 159 Mar 9 11:59 p1.c
-rw-r--r-- 1 root root 1912 Mar 9 19:36 p1.o
-rwxr-xr-x 1 root root 16696 Mar 9 11:31 p1.os
-rw-r--r-- 1 root root 162 Mar 14 23:32 test.c