Linux进程基础

news/2024/12/29 2:30:42/

进程指正在运行的程序,如下图示,是资源分配的最小单位,可以通过“ps ”或“top”等命令查看正 在运行的进程,线程是系统的最小调度单位,一个进程可以拥有多个线程,同一进程里的线程可以共享此 进程的同一资源

 每个进程都有一个唯一的标识符,既进程 ID,简称 pid

进程间的通信的几种方法?

1 管道通信:有名管道,无名管道

2 信号通信:信号的发送,信号的接受,信号的处理

3 IPC 通信:共享内存,消息队列,信号量 

4 Socket 通信

进程的三种基本状态以及转换

 进程创建

所有的进程都是由其他进程创建(除了 pid 为 0 号的 idle 进程),pid 号为 1 的 init 进程是系统启动后 运行的第一个进程,是所有进程的父进程,init 进程会初始化一部分系统服务,创建其他进程。

创建新进程的那个进程称为父进程,新进程称为子进程,父进程和子进程拥有相同的代码段数据段, 有各自独立的地址空间。采用写时拷贝技术,即创建的新进程不会立即把父进程的资源空间复制过来,只 有在修改时才会复制资源,另外父进程挂起的信号和文件锁不会被子进程继承。

子进程结束后,它的父进程要回收它的资源,否则就会成为僵尸进程 。

如果父进程先结束,子进程会被 init 进程收养,称为孤儿进程

创建进程常用函数如下定义:

 实验代码

在程序中,父进程中创建一个子进程。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char const *argv[])
{pid_t pid;int i = 1;pid = fork();if(pid > 0)   //父进程{printf("this is  child  pid: %d   parent pid: %d\n",getpid(),getppid()); printf("parent data: %d \n",i);}else if (pid  == 0)  //子进程{   //sleep(1);   //先运行父进程printf("this is  child  pid: %d\n",getpid());printf("child data: %d \n",i);}else if (pid < 0){printf("cread failed\n");return -1;}return 0;
}

在 Ubuntu 上编译运行,打印进程号如下图所示:

 

exec 函数

用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序,该子进程被新的程序 替换,改变地址空间,进程映像和一些属性,但是 pid 号不变。

exec 函数详解如下表所示:

 以下函数都是根据 execve 实现

int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

实验代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{pid_t pid;char *arr[] = {"ls","-l",NULL};/*exec族函数int execl(const char *path, const char *arg, ... );int execv(const char *path, char *const argv[]);*/pid = fork();if(pid > 0)   //子进程{printf("this is  parent  pid: %d\n",getpid());wait(NULL);     //回收子进程}else if (pid  == 0)  //父进程{   //sleep(1);   //先运行子进程printf("this is  child  pid: %d  parent pid: %d\n",getpid(),getppid()); //execl("/bin/ls","ls","-l",NULL);execv("/bin/ls",arr);      exit(-1);}else if (pid < 0){printf("cread failed\n");return -1;}return 0;
}

执行结果

 

 ps 和 kill 命令

ps 命令:ps 命令可以列出系统中当前运行的那些进程。

命令格式:ps [参数]

命令功能:用来显示当前进程的状态

常用参数: aux

kill 命令:kill 命令用来杀死进程 举例:kill -9(SIGKILL) PI

进程的状态:

D: 无法中断的休眠状态 (通常 IO 的进程)

R: 正在执行中

S: 静止状态

T: 暂停执行

Z: 不存在但暂时无法消除

W: 没有足够的记忆体分页可分配 <: 高优先序的行程

N: 低优先序的行程

L: 有记忆体分页分配并锁在记忆体内 (实时系统或捱 A I/O)

如下所示,使用命令“ps aux | grep a.out”查找到./a.out 的进程号为 3179,然后输入“kill -9 3179”结 束此进程,

 

孤儿进程与僵尸进程:

孤儿进程:父进程结束以后,子进程还未结束,这个子进程就叫做孤儿进程。

僵尸进程:子进程结束以后,父进程还在运行,但是父进程不去释放进程控制块,这个子进程就叫做僵尸 进程。

实验代码 在程序中,创建的子进程变为孤儿进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{int i=0;pid_t pid;// 创建一个子进程pid = fork();if (pid < 0){printf("fork is error \n");return -1;}//父进程 让父进程先结束,并打印进程 PIDif (pid > 0){printf("pid is %d\n", getpid());}//子进程,让子进程等待一会,让父进程先结束,并打印子进程的父进程的 pidif (pid == 0){sleep(2);printf("parent pid is %d\n", getppid());}return 0;
}

编译运行,如下图所示:

 如上图所示,子进程中打印的父进程的进程号和父进程的进程号是不一样的,说明创建的子进程变成 了孤儿进程,此进程被系统的 init 进程"领养"了。

 实验代码 在程序中,子进程变为僵尸进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{int i=0;pid_t pid;
// 创建一个子进程pid = fork();if (pid < 0){printf("fork is error \n");return -1;}//父进程 让父进程先结束,并打印进程 PIif (pid > 0){while(1);}//子进程,让子进程先结束if (pid == 0){printf("This is child\n");exit(0);}return 0;
}

编译运行,如下图所示:

再打开另一个终端,查看此进程如下图所示为僵尸进程。 

 

wait()函数

wait()函数一般用在父进程中等待回收子进程的资源,而防止僵尸进程的产生。

 与 wait 函数的参数有关的俩个宏定义:

WIFEXITED(status):如果子进程正常退出,则该宏定义为真

WEXITSTATUS(status):如果子进程正常退出,则该宏定义的值为子进程的退出值。

实验代码:

在程序中,使用 wait()函数,防止僵尸进程的产生

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{pid_t pid;int start; pid = fork();//让父进程先运行,没有时间去释放进程控制快if(pid > 0)  //父进程{   pid = wait(&start);if (WIFEXITED(start) == 1)   //正常退出为真{printf("return value is %d\n",WEXITSTATUS(start));}}//让子进程先结束else if (pid == 0)   //子进程{   sleep(2);printf("this is child\n");printf("child pid:%d\n",getpid());exit(0);  //对应WEXITSTATUS(start)的退出值}else if (pid < 0){printf("cread fork faile\n");exit(-1);}return 0;
}

编译运行,如下图所示:

 


http://www.ppmy.cn/news/121138.html

相关文章

评测3款高颜值的安卓txt阅读器

txt阅读器作为一种特殊文件的解析软件&#xff0c;把文件解析得精美、吸引人观看&#xff0c;且配套的标注、笔记功能齐全&#xff0c;才能称之为比较合格的txt阅读器。以下是三款适配安卓系统的高颜值txt评测结果&#xff1a; 1.Neat Reader 1颜值很高&#xff0c;打开就让人有…

荣耀笔记本可以JAVA_荣耀笔记本14评测:智能体验 高性能轻薄本新选择

从2018年4月发布第一款笔记本电脑开始&#xff0c;荣耀笔记本走过将近两个年头。凭借不俗的性能和极高的性价比&#xff0c;荣耀笔记本积累了非常不错的用户口碑&#xff0c;诸如Magic-link 2.0魔法互传、多屏协同等功能为用户更来优秀的使用体验。 随着AMD Zen架构的锐龙系列处…

【Android】笔记本

1.设置Android软键盘弹出时不挤压屏幕&#xff0c;或者让界面整体上移&#xff1a; AndroidManifest.xml文件中界面对应的<activity>里加入 android:windowSoftInputMode"adjustPan" 键盘就会覆盖屏幕 android:windowSoftInputMode"stateVisible|adjust…

最强安卓笔记

经过一年的安卓学习&#xff0c;最后要结束了&#xff0c;整理一下&#xff0c;学过的资料包含《疯狂安卓讲义》&#xff0c;《安卓群英传》&#xff0c;《安卓高级开发》&#xff0c;《Android多媒体开发高级编程》和一些平常搜集到的知识点 编写这个博客主要是怀念安卓开发&…

测试笔记本续航的软件,日常应用对比测试_Intel笔记本电脑_笔记本评测-中关村在线...

基本性能表现了解之后&#xff0c;我们看看四个平台在实际应用中的差异。 对于不少用户而言&#xff0c;买电脑大多是为了办公。而办公则会涉及到Office、Photoshop等软件的应用&#xff0c;接下来我们将针对以下几个项目进行测试&#xff1a; 1.Outlook文件整理&#xff1a;将…

安卓笔记1

安卓笔记 智能手机应用类型按钮菜单右上角小菜单上下文菜单 文本框拨打电话显示弹窗消息弹框界面弹框 界面布局显示过长的文本实现水平居中实现水平和垂直居中使用LinearLayout使用ConstrainLayout模块集中方法 实现北南中布局控件隐藏与显示 ConstraintLayout动画界面的动态替…

评测3款高颜值的安卓azw3阅读器

azw3作为一种特殊的电子书文件格式&#xff0c;如何把azw3文件解析得精美、吸引人观看&#xff0c;且配套的标注、笔记功能齐全&#xff0c;才能称之为比较合格的azw3阅读器。以下是三款适配安卓系统的高颜值azw3阅读器评测结果&#xff1a; 1.Neat Reader 1颜值很高&#xff0…

评测3款高颜值的安卓mobi阅读器

mobi最早是亚马逊的一种电子书格式&#xff0c;适用于在kindle上阅读。而现在其实已经有软件可以支持在电脑、手机上阅读了。作为一种特殊的电子书文件格式阅读器&#xff0c;我觉得把mobi文件解析得精美、吸引人观看&#xff0c;且配套的标注、笔记功能齐全&#xff0c;才能称…