当前位置: 首页 > java >正文

进程---基础知识+命令+函数(fork+getpid+exit+wait+exec)

目录

一、进程的定义

二、pcb  

三、PID

四、进程和程序的区别

1.程序

2.进程

五、进程分类

六、进程的状态

七、进程的作用

1.并行

2.并发

八、进程的调度,进程上下文切换

九、查询进程相关命令

1.ps aux

1.1功能

1.2相关状态

2.top

2.1功能

3.kill和killall

3.1功能

3.2用法

十、函数

1.fork();

1.2特性

1.3功能

1.4返回值

1.5代码实现

2.getpid

2.1函数原型

2.2功能

2.3参数

2.4返回值

3.getppid  parent

3.1函数原型

3.2功能

3.3参数

3.4返回值

十一、父子进程的关系与区别

1.关系

2.区别

十二、进程的终止

1.主动退出

2.异常终止

3.代码实现

3.1exit()

3.2_exit()

十三、僵尸进程和孤儿进程

1.孤儿进程

2.僵尸进程

十四、回调函数

atexit

1.函数原型

2.功能

3.参数

4.返回值

5.注

6.代码示例

十五、进程空间的回收

1.wait

1.1函数原型

1.2功能

1.3参数

1.4返回值

1.5宏值

1.6代码示例

2.waitpid

2.1函数原型

2.2功能

2.3参数

2.4返回值

2.5代码示例

十六、进程替换函数族---exec函数族(execute)

1.定义

2.特性

3.分类

3.1execl

3.2execlp

3.3execv

3.4execvp


一、进程的定义

进程是一个程序执行的过程,会去分配内存资源,cpu的调度

二、pcb  

是一个结构体,process control block  print circuit board

vim -t
task_struct 

三、PID

进程标识符

当前工作路径   chdir
umask  0002
进程打开的文件列表  文件IO中有提到
信号相关设置 处理异步io,
用户id,组id
进程资源的上限
ulimit -a,显示资源上限。

四、进程和程序的区别

1.程序

静态,存储在硬盘中代码,数据的集合

2.进程

动态,程序执行的过程,包括进程的创建、调度、消亡

.c ----> a.out-----> process(pid)
1)程序是永存,进程是暂时的
2)进程有程序状态的变化,程序没有
3)进程可以并发,程序无并发
4)进程与进程会存在竞争计算机的资源
5)一个程序可以运行多次,变成多个进程
一个进程可以运行一个或多个程序
内存的分布
0-3G,是进程的空间,3G-4G是内核的空间,虚拟地址
虚拟地址 *  物理内存和虚拟内存的地址 映射表 1page=4k    mmu

五、进程分类

1.交互式进程
2.批处理进程   shell脚本 
3.守护进程 

六、进程的状态

3个状态:就绪→执行态→阻塞(等待,睡眠)基本操作系统

linux中的状态,运行态,睡眠态,僵尸,暂停态。

七、进程的作用

1.并行

进程在多个cpu上运行

2.并发

进程在一个cpu上运行

八、进程的调度,进程上下文切换

内核主要功能之一就是完成进程调度, 硬件,bios,io,文件系统,驱动

调度算法, other,idle
rr,fifo  
rt_thread ucos 
先来先服务
短任务优先
优先级, 时间片

宏观并行
微观串行

九、查询进程相关命令

1.ps aux

1.1功能

查看进程相关信息

1.2相关状态

1)就绪态、运行态 R
2)睡眠态、等待态
        可唤醒等待态 S
        不可唤醒等待态 D
3)停止态 T
4)僵尸态 Z
5)结束态

2.top

2.1功能

根据CPU占用率查看进程相关信息

3.kill和killall

3.1功能

发送一个信号

3.2用法

1)kill -2 PID  

发送信号+PID对应的进程,默认接收者关闭

2)kill -9 PID  

发送信号+PID对应的进程,强制接收者关闭

3)killall -9 进程名

发送信号 进程名对应的所有进程

killall a.out

十、函数

1.fork();

1.1函数原型

pid_t fork(); 叉子

1.2特性

一次调用,会返回两次。

子进程先运行和是父进程先进程,顺序不确定。

变量不共享。

子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。

1.3功能

通过该函数可以从当前进程中克隆一个同名新进程。
  克隆的进程称为子进程,原有的进程称为 父进程。
  子进程是父进程的完全拷贝。
  子进程的执行过程是从fork函数之后执行。
  
  子进程与父进程具有相同的代码逻辑。

1.4返回值

int 类型的数字

1)在父进程中:成功 返回值是子进程的pid号 >0
失败 返回-1;

2)在子进程中:成功 返回值 0
失败 无

1.5代码实现

#include <stdio.h>
// #include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char **argv)
{pid_t ret = fork();if (ret > 0)  //父进程 ---ret是子进程的id{while (1){printf("发送视频...\n");sleep(1);}}else if (0 == ret)  //子进程{while (1){printf("接受控制\n");sleep(1);}}else{perror("fork error\n");return 1;}return 0;// system("pause");return 0;
}

变量不共享代码示例

#include <stdio.h>
// #include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>//变量不共享int a = 5;
int main(int argc, char **argv)
{pid_t ret = fork();if (ret > 0){sleep(5);printf("father a is %d\n", a);}else if (0 == ret){a += 5;printf("child a is %d\n", a);sleep(1);}else{perror("fork error\n");return 1;}//父进程和子进程都会走一遍---打印两边printf("a is %d\n", a);return 0;// system("pause");return 0;
}

2.getpid

2.1函数原型

pid_t getpid(void);

2.2功能

获得调用该函数进程的pid

2.3参数

缺省

2.4返回值

进程的pid

2.5代码实现

#include <stdio.h>
// #include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char **argv)
{pid_t ret = fork();if (ret > 0){int i = 5;while (i){printf("父进程 发送视频...pid:%d ppid:%d\n", getpid(), getppid());sleep(1);i--;}}else if (0 == ret){int i = 5;while (i){printf("子进程 接受控制...pid:%d ppid:%d\n", getpid(), getppid());sleep(1);i--;}}else{perror("fork error\n");return 1;}printf("pid:%d ppid:%d\n", getpid(), getppid());return 0;// system("pause");return 0;
}

3.getppid  parent

3.1函数原型

pid_t getppid(void);

3.2功能

获得调用该函数进程的父进程pid号

3.3参数

缺省

3.4返回值

返回父进程id号

fork()&&fork()||fork();

十一、父子进程的关系与区别

1.关系

子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。

在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制

2.区别

1)fork的返回值   >0    ==0
2)pid不同

十二、进程的终止

1.主动退出

1)main 中return
2)exit(), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理函数(atexit)。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4) 主线程退出
5)主线程调用pthread_exit

2.异常终止

6)abort()
7)signal   kill pid
8)最后一个线程被pthread_cancle

3.代码实现

3.1exit()

#include <stdio.h>
#include <stdlib.h>int	main(int argc, char **argv)
{printf("hello");exit(EXIT_SUCCESS);printf("---------end----------\n");// system("pause");return 0;
}

3.2_exit()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int	main(int argc, char **argv)
{printf("hello");_exit(EXIT_SUCCESS);printf("------------------\n");// system("pause");return 0;
}

十三、僵尸进程和孤儿进程

1.孤儿进程

父进程提前终止,但是子进程还在运行中,父进程无法对子进程进行监管,子进程就成为了孤儿进程。

2.僵尸进程

子进程运行已经结束,但是父进程没有对其资源回收,导致子进程不能彻底退出,在僵尸状态,进程表中仍然会保留僵尸进程的PCB,占用系统资源。

十四、回调函数

atexit

1.函数原型

int atexit(void (*function)(void));

2.功能

注册进程退出前执行的函数

3.参数

function:函数指针
指向void返回值void参数的函数指针

4.返回值

成功返回0
失败返回非0

5.注

当程序调用exit或者由main函数执行return时,所有用atexit注册的退出函数,将会由注册时顺序倒序被调用

6.代码示例

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
char *p;
int fd;
void clean()
{printf("clean---p:%s fd:%d\n", p, fd);free(p);close(fd);
}
int main(int argc, char **argv)
{atexit(clean);p = malloc(10);fd = open("1.txt", O_RDONLY);printf("in procing.....\n");strcpy(p, "hello");char buf[10] = {0};read(fd, buf, 10);printf("before return \n");// system("pause");return 0;
}

十五、进程空间的回收

exit(20);

1.wait

1.1函数原型

pid_t wait(int *status);

1.2功能

2.1该函数可以阻塞等待任意子进程退出,并回收该进程的状态。

2.2一般用于父进程回收子进程状态。

2.3子进程若是没有消亡,父进程则会等待子进程消亡才会回收

1.3参数

status 进程退出时候的状态
  如果不关心其退出状态一般用NULL表示
  如果要回收进程退出状态,则用WEXITSTATUS回收。

1.4返回值

成功回收的子进程pid
失败 -1;

1.5宏值

5.1WIFEXITED(status)  是不是正常结束

WEXITSTATUS(status) 使用这个宏去那返回值

5.2WIFSIGNALED(status) 是不是收到了信号而终止的

WTERMSIG(status)如果是信号终止的,那么是几号信号。

1.6代码示例

#include <stdio.h>
// #include <stdlib.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main(int argc, char **argv)
{pid_t pid = fork();if (pid > 0){printf("father pid:%d\n", getpid());wait(NULL);printf("recycle end\n");}else if (0 == pid){sleep(3);printf("child pid:%d\n", getpid());exit(1);}else{perror("fork error");return 1;}// system("pause");return 0;
}

2.waitpid

2.1函数原型

pid_t waitpid(pid_t pid, int *status, int options);

2.2功能

< -1 回收指定进程组内的任意子进程
-1 回收任意子进程,组内外
0 回收和当前调用waitpid一个组的所有子进程,组内
> 0 回收指定ID的子进程

2.3参数

status 子进程退出时候的状态,
   如果不关注退出状态用NULL;
options 选项:
   0  表示回收过程会阻塞等待
WNOHANG 表示非阻塞模式回收资源。

2.4返回值

返回值:成功 返回接收资源的子进程pid
失败  -1

2.5代码示例

十六、进程替换函数族---exec函数族(execute)

1.定义

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。

2.特性

当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。

调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

3.分类

3.1execl

3.1.1函数原型

int execl(const char *path, const char *arg,...

                        /* (char  *) NULL */);

3.1.2代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char **argv)
{//实现终端命令ls -a -l//实现./a.out -a -lexecl("/bin/ls", "ls", "-a", "-l", "--color=auto", NULL);printf("看见就错了\n");// system("pause");return 0;
}

3.2execlp

3.2.1函数原型

int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);

3.2.2代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char **argv)
{//实现终端命令ls -a -l//实现./a.out -a -l// execl("/bin/ls", "ls", "-a", "-l", "--color=auto", NULL);//从firefox打开www.baidu.comexeclp("/usr/bin/firefox", "firefox", "www.baidu.com", NULL);printf("看见就错了\n");// system("pause");return 0;
}

3.3execv

3.3.1函数原型

 int execv(const char *path, char *const argv[ ]);

3.3.2代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, const char *argv[])
{// ls -a -l//  ./a.out -a -l     execute   argument list// execl("/bin/ls","ls","-a","-l","--color=auto",NULL); list argument// execlp("ls","ls","-a","-l","--color=auto",NULL); echo $PATHchar *const args[] = {"ls", "-a", "-l", "--color=auto", NULL};execv("/bin/ls", args);  // vector  数组printf("看见就错了\n");// system("pause");return 0;
}

3.4execvp

3.4.1函数原型

 int execvp(const char *file, char *const argv[ ]);

3.4.2代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, const char *argv[])
{// ls -a -l//  ./a.out -a -l     execute   argument list// execl("/bin/ls","ls","-a","-l","--color=auto",NULL); list argument// execlp("ls","ls","-a","-l","--color=auto",NULL); echo $PATHchar *const args[] = {"ls", "-a", "-l", "--color=auto", NULL};// execv("/bin/ls",args);//vector  数组execvp(args[0], args);printf("看见就错了\n");// system("pause");return 0;
}

http://www.xdnf.cn/news/15393.html

相关文章:

  • ACL流量控制实验
  • 12.如何判断字符串是否为空?
  • 记字节前端面试一道简单的算法题
  • 游戏玩法的专利博弈
  • 大话数据结构之 <链表>(C语言)
  • 使用 keytool 在服务器上导入证书操作指南(SSL 证书验证错误处理)
  • 【DOCKER】-4 dockerfile镜像管理
  • Python数据容器-通用功能
  • grpo nl2sql qwen3 模型强化学习训练有效果的成立条件有哪些
  • java--ThreadLocal创建以及get源码解析
  • 131. Java 泛型 - 目标类型与泛型推断
  • RNN(循环神经网络)
  • js与vue基础学习
  • Cesium源码打包
  • 从数据库到播放器:Java视频续播功能完整实现解析
  • Netty编程模型介绍
  • 聚宽sql数据库传递
  • 【WPF】WPF 自定义控件 实战详解,含命令实现
  • Node.js + Express的数据库AB View切换方案设计
  • 渗透笔记1-4
  • vim扩展
  • Spring Boot Cucumber 测试报告嵌入方法
  • Linux 基础命令详解:从入门到实践(1)
  • 微前端框架深度对决:qiankun、micro-app、wujie 技术内幕与架构选型指南
  • MFC UI表格制作从专家到入门
  • MyBatis 在执行 SQL 时找不到名为 name 的参数
  • Unsloth 实战:DeepSeek-R1 模型高效微调指南(下篇)
  • LeetCode 424.替换后的最长重复字符
  • Android展示加载PDF
  • 深入学习前端 Proxy 和 Reflect:现代 JavaScript 元编程核心