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

阿里云主机网站开发河北省沧州建设厅网站

阿里云主机网站开发,河北省沧州建设厅网站,备案的域名拿来做别的网站,泰国一家做男模的网站往期文章#xff1a;《Linux#xff1a;深入了解冯诺依曼结构与操作系统》 Linux#xff1a;深入理解冯诺依曼结构与操作系统-CSDN博客 目录 1. 概念 2. 描述进程 3. 深入理解进程的本质 4. 进程PID 4.1 指令获取PID 4.2 geipid函数获取PID 4.3 kill指令终止进程 …往期文章《Linux深入了解冯诺依曼结构与操作系统》 Linux深入理解冯诺依曼结构与操作系统-CSDN博客 目录 1. 概念 2. 描述进程 3. 深入理解进程的本质 4. 进程PID 4.1 指令获取PID 4.2 geipid函数获取PID 4.3 kill指令终止进程 4.4 进程信息文件夹 1exe 2cwd 5. 进程PPID 5.1 getppid函数获取PPID 5.2 fork函数创建子进程 6. 创建多进程 7. fork函数如何返回两个值 1. 概念 进程Process是指一个正在执行的程序实例。在操作系统中进程是资源分配和调度的基本单位。可执行程序与进程的区别可执行程序是一组指令的集合它存储在磁盘上而进程则是程序在执行时的一个实例它存在于内存中。 2. 描述进程 操作系统也称之为Operating System缩写就是OS。 操作系统笼统的分为内核(kernel)和外壳程序。内核有进程管理、内存管理、文件管理和驱动管理。操作系统管理任何对象都是对其属性进行管理遵守先描述再组织的原则。 因此操作系统管理进程相当于管理它的属性会把进程属性放在一个叫做进程信息控制块的数据结构当中就是进程属性的集合。这也称为PCBprocess control blockLinux操作系统下的PCB是task_struct。 下面是task_struct结构体中包含的内容 标示符: 描述本进程的唯一标示符用来区别其他进程。状态: 任务状态退出代码退出信号等。优先级: 相对于其他进程的优先级。程序计数器: 程序中即将被执行的下一条指令的地址。内存指针: 包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针。上下文数据: 进程执行时处理器的寄存器中的数据[休学例子要加图CPU寄存器]。IO状态信息: 包括显示的I/O请求,分配给进程的IO设备和被进程使用的文件列表。记账信息: 可能包括处理器时间总和使用的时钟数总和时间限制记账号等。其他信息 3. 深入理解进程的本质 如下图进程的前身就是一个可执行程序它主要包含代码和数据且在硬盘当中。可执行程序在windows系统中一般以.exe结尾在Linux系统中一般没有特定的后缀结尾且通常不跟后缀。 当一个可执行程序启动运行时其代码与数据将被载入内存之中。在这一过程之前操作系统内核会创建一个名为task_struct的结构体对象该对象详细记录了进程的各种属性。这些属性包括但不限于进程标识符pid、状态信息、优先级等。特别地memptr指针负责记录内存中myexe程序的起始地址确保进程能够正确地访问和执行程序代码。 进程 内核数据结构(task_struct) 程序的代码和数据 当多个可执行程序同时运行时task_struct结构体内部采用特定的数据结构将所有进程串联起来。设想task_struct中包含一个指向下一个结构体的指针那么将存在一个结构体指针list它指向链表中的第一个task_struct对象。随着新进程的创建它们的task_struct对象会被前一个对象的next指针串联起来从而在操作系统中形成了一个调度队列。 CPU的寄存器并不直接存储程序的代码和数据而是通过list指针定位到相应的task_struct对象并将其信息载入寄存器。因此当CPU调度内存中的myexe进程时实际上是在操作该进程的task_struct对象进而间接执行程序代码。 我们可以用一个类比来理解这个过程假设张三正在求职他提交了一份简历给公司的人力资源部门HR。这份简历包含了张三的个人详细信息、实习经历和项目经验这些信息集合就如同进程的task_struct结构体记录了张三的“属性”。当HR收到众多简历并逐一审核时求职者本人对于这一过程是一无所知的。这与CPU调度进程的情形相似CPU并不直接运行内存中的程序而是通过操作task_struct结构体对象来间接实现对进程的调度。 4. 进程PID 4.1 指令获取PID 不管是在windows系统中你双击某个应用还是在Linux系统中你执行某些指令或者运行某个可执行程序当这些程序跑起来都叫做进程。不过进程一般分为两种第一种是执行完就退出的进程像Linux系统下的ls pwd等指令第二种是执行完一直不退出直到用户关闭像window系统中的QQ微信等应用这种进程叫做常驻型进程。 下面写一份C语言代码在main函数使用while循环搞个死循环内部是每隔一秒钟打印一句话。sleep函数的作用是使当前进程暂停执行指定的秒数该函数的原型通常在unistd.h头文件中定义 当程序运行起来会不断打印“hello linux”。 这时我们再打开一个Xshell程序就可以在不打扰上面进程的情况下输入新指令并运行。 我们可以使用ps指令来查看进程信息。其中head -1表示拿到进程信息的第一行grep加某些进程名表示拿到该进程名那行信息。你会发现COMMAND这列中含有grep指令这是因为gerp myproc本身就含有myproc也会打印出来。想要去掉它grep后加上-v grep就是忽略grep相关的文本信息。 -a显示所有终端下的进程。-x显示没有控制终端的进程在后台运行。-j显示与作业控制相关的信息。 我们观察上图第一行中有许多属性名词其中PID表示进程的唯一标识符PPID表示父进程的标识符。myproc进程pid是4340。如果我们按下CtrlC按键会中断该进程。 当再次启动进程时使用ps指令获取进程信息pid值为6336。你会发现同样都是myproc的进程pid值发生改变。因为系统使用一个累加的计数器维护进程的PID值在你启动进程时操作系统也不断在请求任务。所以PID值出现变化且不连续是很正常的。 4.2 geipid函数获取PID getpid是一个系统调用级函数可以获取进程的id值。需要包含两个头文件分别是unistd.h和sys/types.h。其中pid_t其实本质就是long int类型只不过被typedef封装了一下。 使用getpid函数不用频繁获取只需获取一次因为一个进程启动之后id值不会改变的除非重新启动一次。当myproc程序执行起来后可以看到进程id值是8042。我们使用ps指令获取myproc进程的信息会发现pid值也是8042。 4.3 kill指令终止进程 如果你想要终止一个进程可以在键盘上按下Ctrl C的按键发出终止信号。或者使用kill指令使用kill -l可以查看kill指令的选项其中9对应的选项就是终止进程。 终止进程操作如上图所示输入kill -9 进程id值在另外一恶搞Xshell程序中可以看到myproc进程停止显示了Killed信息。 4.4 进程信息文件夹 1exe 我们刚刚通过ps指令可以获取进程的一部分信息。在Linux操作系统下一切皆文件。我们使用ls指令查看根目录会发现有个proc目录。 proc就是process(进程)的缩写再使用ls指令查看该目录可以发现许多以数字命名的目录这些就是某个进程的id值里面存放的就是该进程的相关信息。 运行myproc程序后生成一个pid值为19775的进程使用ls命令查看/proc路径下的文件其中就有名为19775文件夹。该文件夹存放的就是该进程的详细信息。 我们查看/proc/19775路径下的文件会发现里面有许多内容。今天需要认识一下exe和cwd。进程是被某个可执行程序启动exe存放的就是该可执行程序的路径 当我们再打开一个Xshell程序进入到myproc的目录下删除该可执行程序你会发现进程还是在运行。因为进程已经被加载到内存当中删除硬盘的可执行程序不会造成影响。但是再次查看/proc/19775路径下的文件会发现exe显示该路径下的可执行程序已被删除。 2cwd cwd全称是current working directory意思是当前工作目录。我们在C语言中创建一个文件如果没有指定绝对路径默认生成在当前路径下。下面我们写个代码验证一下。 运行myproc程序过几秒终止进程。查看当前目录会发现多了一个file.txt文件。所以使用fopen新建一个文件时不是你以为的相对路径而是拿到cwd再加上你输入的文件名形成一个绝对路径。还有什么方式可以证明上面的说法呢 我们可以使用一个系统调用函数chdir它的作用就是改变当前进程的工作目录。我们在myproc.c中使用chdir函数修改当前工作目录为home目录下的普通用户也就是我正在使用的用户。如果修改到根目录或者家目录无法新建文件夹因为普通用户没有写权限只有超级用户才可以新建文件或者目录。 当我们启动myproc程序后立即查看/proc/24404中内容会发现cwd变成了普通用户的目录。再使用ls命令查看工作目录发现有file.txt文件。这就验证了在代码中新建文件如果不写绝对路径会在输入的文件名前加上当前工作目录。 5. 进程PPID 5.1 getppid函数获取PPID ppid是指parent process id即某个进程的父进程id值。 其中getppid函数是获取某个进程的父进程id值。 修改一下myproc.c中的代码获取一下父进程id并打印出来。 当我们启动myproc程序运行一会后终止该程序再启动该程序重复三次。你会发现它们的父进程id值都是19496。 我们使用ps指令查看该父进程信息发现该进程的command执行的指令是-bash。其中bash是Linux系统下的命令行解释器类似于windows系统中的cmd。 因此有个结论在Linux操作系统启动之后命令行上执行指令或者执行程序本质上都是bash的进程创建的子进程由这些子进程执行我们的代码 5.2 fork函数创建子进程 fork函数也是系统调用函数。函数原型如上返回值类型是pid_t不用传参。它的作用是在当前进程下创建一个子进程。 修改myproc.c中的代码一开始打印一下当前进程的pid和ppid。之后调用fork函数试着打印子进程的pid和ppid。 运行myproc程序你会发现打印了三行语句。其中第一行语句是第一个printf函数打印的pid值为29447的进程应该是myproc启动后的进程它的父进程就是上面提到的bash。 但是下面打印了两行语句第二行语句的pid值为29447ppid值是26892应该是当前程序的进程。最后一行语句中pid值是29448ppid值是29447它的父进程就是myproc程序启动后的进程说明这是fork函数创建出来的子进程并且pid值是连续的。 可以得出结论调用fork函数当前进程会创建一个子进程这两个进程会同时执行后面的代码相当于两个执行流分支。因为这两个进程是连续创建的它们的pid值连续。 #include stdio.h #include unistd.h #include sys/types.hint main() {printf(I am a process, pid: %d, ppid: %d\n, getpid(), getppid());pid_t id fork();if (id 0){while (1){printf(我是父进程pid: %d, ppid: %d, ret id: %d\n, getpid(), getppid(), id);sleep(1);}}else if (id 0){while (1){printf(我是子进程pid: %d, ppid: %d, ret id: %d\n, getpid(), getppid(), id);sleep(1);}}} fork函数调用成功给父进程返回子进程的pid给子进程返回0。如果调用失败会设置错误值到errno变量中。 运行结果如上fork创建进程后当前进程接收到子进程的id值子进程接收到0。那么为什么if else语句看起来能同时成立且有两个返回值 上面有提到进程 内核数据结构(task_struct) 程序的代码和数据。那么fork函数创建一个子进程时操作系统会创建一个task_struct结构体对象。程序中的代码因为是只读的子进程与父进程共享代码。 而子进程会私有一份数据因为两个进程间数据互相修改可能会触发某些条件导致程序崩溃所以进程之间具有很强的独立性一个进程崩溃不会影响另外一个进程。这就类似于手机上启动许多应用如微信抖音等如果微信崩溃不会影响抖音的运行。 因为fork函数创建子进程后会出现两个执行流那么此时fork函数返回一个值时有两个执行流进行返回并且进程间的数据是各自私有的那么id变量会有两份。 #include stdio.h #include unistd.h #include sys/types.hint g_val 0;int main() {printf(I am a process, pid: %d, ppid: %d\n, getpid(), getppid());pid_t id fork();if(id 0){while(1){printf(我是父进程pid: %d, ppid: %d, ret id: %d, g_val: %d\n, getpid(), getppid(), id, g_val);sleep(1);}}else if(id 0){while(1){printf(我是子进程pid: %d, ppid: %d, ret id: %d, g_val: %d\n, getpid(), getppid(), id, g_val);g_val;sleep(1);}}} 如上我们可以定义一个全局变量g_val在父进程中只打印出来在子进程中不仅打印出来每次让g_val变量加1。 结果如上父进程的g_val值一直是0子进程的g_val值不断变化。这就证明了子进程会私有一份数据。 6. 创建多进程 #include iostream #include unistd.h #include vector #include sys/types.h using namespace std;const int num 10;void SubProcessRun() {while(true){cout I am a sub process, pid: getpid() ,ppid: getppid()endl;sleep(5);} }int main() { vectorpid_t childproc;for(int i 0; i num; i){pid_t id fork();if (id 0){//子进程SubProcessRun();}//走到这里只能是父进程执行childproc.push_back(id);}//父进程遍历所有子进程的pidcout 我的所有子进程:;for(auto child: childproc){coutchild ;}cout endl;sleep(10);while(true){cout 我是父进程pid: getpid()endl;sleep(1);}return 0; }使用一个for循环使用fork创建子进程。每个子进程再调用SubProcessRun函数死循环不断打印pid值。 使用vector数组存储子进程的pid值然后遍历打印出来。父进程也执行个死循环不退出。 运行该程序就可以一次性创建多个连续进程。 7. fork函数如何返回两个值 fork函数为什么会返回两个返回值 因为fork函数内部再返回值之前会先创建子进程创建进程会先在内核中创建task_struct结构体对象用于管理进程的属性然后代码共享数据拷贝父进程的。这时子进程已经开始运行那么就会有两个执行流最后返回值也是代码就会被父子进程各自返回一次。 不过还有一个问题没有弄清楚return语句返回的是一个值。为什么两个执行流返回时这个值就变成两个不同的值这是后面会解决的问题。 创作充满挑战但若我的文章能为你带来一丝启发或帮助那便是我最大的荣幸。如果你喜欢这篇文章请不吝点赞、评论和分享你的支持是我继续创作的最大动力
http://www.dnsts.com.cn/news/69001.html

相关文章:

  • 做零售出口的网站网站建设团队哪个最好
  • 网站建设方案-奢侈品广告优化是做什么的
  • 怎样做付费下载的网站网站建设分金手指排名五
  • 搭配服装网站源码建设网站选题应遵循的规则
  • 广州智迅网络做网站住房城乡建设部网站职业资格
  • 长春企业网站seo招聘网站分析报告怎么做
  • 自适应手机网站模板企业站seo外包
  • 做推文的编辑网站织梦网站防黑怎么做
  • 淘客怎么做推广网站大连本地网
  • cad图做网站链接该如何建设和优化一个网站
  • 电商网站建设实训心得wordpress 有道云笔记
  • 无锡响应式网站设计杭州网站界面设计
  • 管理咨询公司企业简介东莞seo关键词
  • 十个源码网站做围棋题最好的网站
  • 汕头网站建设方案外包营销型网站建设方案
  • 选择建设网站公司要注意什么ppt一键生成免费版
  • 公司做网站需要几个人北京公司摇号
  • 兼职制作网站开发wordpress默认固定链接
  • 深圳建设岗位证书报名网站京美建站官网
  • 网站页面ps网站头部
  • 鹤壁公司做网站十堰网站建设怎么做
  • 公司网站一定要域名吗什么是网络营销含义
  • 网站 建设 公司手机网站有什么要求
  • 河南英文网站建设公司网上商城怎样推广
  • 珠海市建设局官方网站静态网站开发实训的目的
  • 旅游网页设计模板网站南川网站建设
  • 张江网站建设wordpress知识问答主题
  • 商城用什么系统做网站手机设计效果图制作软件
  • 网站用户黏度表现在定制建站 app建设
  • 深圳罗湖网站制作公司哪家好wordpress创建配置文件