【Linux进程】查看进程fork创建进程

目录

前言

 1. 查看进程

 2. 通过系统调用创建进程-fork初识

总结


前言

         你有没有想过在使用Linux操作系统时,后台运行的程序是如何管理的?在Linux中,进程是一个非常重要的概念。本文将介绍如何查看当前运行的进程,并且讨论如何使用fork创建新的进程。通过了解这些内容,你将更好地理解Linux系统中的进程管理。

在这里插入图片描述

 1. 查看进程

          在理解进程状态之前,我们要先学会查看进程,进程的信息可以通过 /proc 系统文件夹查看 

 ls /proc

 可以看到有很多以数字命名的文件夹,这些数字其实就是进程的PID:

 进行实验的代码:

#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>int main(){pid_t id = getpid();pid_t fid = getppid();while(1){printf("Hello world! pid: %d ppid: %d\n",id,fid);                                                  sleep(1);}return 0;}

 指令:

 ls /proc/【PID】 -ld

 进一步查看进程详细信息:

ls /proc/【PID】 -l

 里边的文件都是进程的属性,这里有两个显眼的属性cwd和exe

  •  exe:进程可执行程序在磁盘中对应的位置
  •  cwd(current working directory):进程的当前工作目录

进程在运行时,它的可执行程序会被加载到内存当中,在进程运行的情况下我们依然可以删除它的可执行程序。删除之后再次查看运行中进程属性就会发现exe属性被标红且高亮闪烁

 在C语言中我们对文件进行操作:

fopen("file.txt" , " w");

这里也解释了,在没有这个文件时为什么会默认在程序的当前目录下创建。因为那是进程的工作目录;我们也可以通过修改进程工作目录的方式,改变创建文件的默认路径。

 我们可以调用chdir这个系统调用接口来改变进程的工作目录,以下时chdir的相关说明文档:

 使用时直接指定新路径即可,成功返回0,失败返回-1.

 实验代码:

int main()
{printf("self pid: %d\n", getpid());chdir("/home/test");FILE *fp = fopen("test.txt", "w");if(fp == NULL) return 1;fclose(fp);printf("新建文件完成\n");sleep(50); //50秒后结束运行,预留充足实际去查询进程}

 在程序运行结束之前,查看进程的属性时发现,进程的工作目录被修改为了:/home/test

 程序运行结束之后发现test.txt文件出现在/home/test目录下。

 2. 通过系统调用创建进程-fork初识

 查看fork操作手册:

man fork

 退出时输入q即可

 man指令前边文章提到过,查看命令手册页的命令,在面对一个新的指令或者未知的指令我们都可以使用man查看,面对一些系统调用接口时也可以使用。

在查看时说明文档或许很长,我们如果是需要快速上手使用,可以主要看3部分:

  • synopsis (所属头文件、返回值类型)
  • description(接口基本功能)
  • return value (具体返回值)

fork基本信息:

  • 作用:创建一个子进程,
  • 返回类型:pid_t
  • 返回值:创建成功返回子进程的PID给父进程,返回0给子进程,失败返回-1给父进程

 我们可以实验一下:

实验代码:

#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>int main()
{printf("before fork: I am a prcess, pid: %d, ppid: %d\n", getpid(), getppid());pid_t id = fork();printf("after fork: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);                                      sleep(2);return 0;
}

 运行结果:

 fork之后,运行了两次,原进程和子进程,fork之后代码共享,子进程会继承父进程大部分属性,子进程从fork之后执行

 原进程的父进程12333是谁? 其实是bash命令行解释器。

指令查看:

 ps ajx | grep pid

  •  为什么父进程返回子进程PID,子进程返回0 ?

        父进程与子进程的关系是1:n的关系,子进程有有唯一的父进程,而父进程为了辨别每个子进程就需要通过进程唯一的标识PID。

  • fork函数为什么会返回两次?

        fork函数功能是创建一个新的进程(子进程),子进程会继承父进程大部分属性,父进程调用fork函数执行到return时,子进程已经被创建,此时子进程继承了父进程状态,也是执行到return位置,父进程return一次,子进程return一次,所以它会执行两次。

  • id一个变量怎么可能同时大于0和等于0?

 进程在设计之初就被要求相互独立,互不影响,下面是一个测试样例:

父进程和子进程一起执行,使用kill指令发送信号杀死父进程,子进程不受影响依然可以运行。

 测试使用的指令:

while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done

 杀死进程:

kill -9 PID

 主要在进程运行界面杀死进程不能用ctrl c(会同时终止两个进程)。

 使用的代码

#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>int main()
{printf("before fork: I am a prcess, pid: %d, ppid: %d\n", getpid(), getppid());sleep(5);printf("开始创建进程\n");sleep(1);pid_t id = fork();if(id < 0) return 1;else if(id == 0){// 子进程while(1){printf("after fork, 子进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);sleep(1);}}else{// 父进程while(1){printf("after fork, 父进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);sleep(1);}}sleep(2);return 0;
}

 操作系统在设计进程之初就必须要考虑到进程相互独立这一点。

前边我们提到fork之后代码和数据共享,如果某一个进程修改了数据会不会对另一个进程造成影响?

        不会,操作系统为了使进程互不影响,某个进程(父进程或子进程)在修改数据时,操作系统会进行写时拷贝,进程修改数据时OS会单独开一块空间将数据复制一份交给(修改的数据)进程,修改数据也就是对新拷贝的数据进行修改。Linux中可以用同一个变量名,表示不同的内存空间。


总结

         进程是Linux操作系统中一个非常重要的概念,对于系统的管理和性能至关重要。通过本文的介绍,希望你对于Linux进程有了更深入的了解。在实际应用中,进程管理涉及到更多的细节和技巧。以上便是本文全部内容,希望对你有所帮助,感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/340718.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

由于找不到msvcp140.dll无法继续执行代码原因及解决教程分享

在计算机打开软件过程&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“由于找不到msvcp140.dll无法继续执行代码”。这个错误通常发生在使用Microsoft Visual C 2015或更高版本编译的程序运行时。那么&#xff0c;什么是msvcp140.dll文件&#xff1f;为什么会…

深入Go语言:高效基准测试与性能分析指南

基准测试 1. 编写 测试代码 基准测试在 Go 中通常是以 Benchmark 开头的函数&#xff0c;接受一个 *testing.B 类型的参数。这个参数提供了控制基准测试运行的方法&#xff0c;比如指定测试运行的次数。 func BenchmarkServer_XX(b *testing.B) {// 准备测试的 Server 实例和…

如何进行大数据系统测试

大数据系统常见的架构形式有如下几种&#xff1a; Hadoop架构&#xff1a; Hadoop Distributed File System (HDFS)&#xff1a;这是一种分布式文件系统&#xff0c;设计用于存储海量数据并允许跨多台机器进行高效访问。 MapReduce&#xff1a;作为Hadoop的核心计算框架&#…

如何在Github上快速下载代码

由于网络环境问题&#xff0c;有时候比较难从Github上下载代码&#xff0c;我归纳了以下三种从Github上下载代码的方法&#xff0c;如何选择使用&#xff0c;可根据你的实际情况&#xff1a; 目录 方法一&#xff1a;使用 “Download ZIP” 按钮 方法二&#xff1a;使用 Git…

【浅尝C++】引用

&#x1f388;归属专栏&#xff1a;浅尝C &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;记录一句&#xff1a;大半夜写博客的感觉就是不一样&#xff01;&#xff01; 文章前言&#xff1a;本篇文章简要介绍C中的引用&#xff0c;每个介绍的技术点&#xff0c;在…

上架苹果APP的时候在哪里填写APP的隐私政策信息

在如今高度重视数据隐私的时代&#xff0c;开发并上架一个iOS APP时提供透明的隐私政策是非常重要的。苹果公司对此有严格的规定&#xff0c;任何上架至App Store的应用都必须包含一个隐私政策。以下是您在上架苹果APP时填写隐私政策信息的详细步骤和必须注意的事项。 准备隐私…

Centos7升级openssl到openssl1.1.1

Centos7升级openssl到openssl1.1.1 1、先查看openssl版本&#xff1a;openssl version 2、Centos7升级openssl到openssl1.1.1 升级步骤 #1、更新所有现有的软件包列表并安装最新的软件包&#xff1a; $sudo yum update #2、接下来&#xff0c;我们需要从源代码编译和构建OpenS…

平时执行很快的SQL语句,为什么会突然卡一下?

InnoDB在处理更新语句的时候&#xff0c;只做了写日志这一个磁盘操作&#xff0c;这个日志叫作redo log&#xff08;重做日志&#xff09;&#xff0c;在更新内存写完redo log后&#xff0c;就返回给客户端&#xff0c;本次更新成功。 把内存里的数据写入磁盘的过程&#xff0…

Electron中调用dll

截止目前Electron的官方稳定版本已经更新到了28.1.1。我在创建Electron项目时用的28.0.0版本&#xff0c;后面在项目中有用到调用dll方法的需求&#xff0c;大致的实现就是将后端给的dll文件引入到项目中&#xff0c;安装ffi-napi依赖&#xff0c;然后进行使用。但是在Electron…

ROS---激光雷达的使用

ROS—激光雷达的使用 激光雷达是现今机器人尤其是无人车领域及最重要、最关键也是最常见的传感器之一&#xff0c;是机器人感知外界的一种重要手段。本文将介绍在ROS下使用激光雷达传感器&#xff0c;我们选用的激光雷达型号为思岚A1。 使用流程如下: 硬件准备&#xff1b;软…

什么是集成测试?

什么是集成测试 集成测试&#xff08;Integration Testing&#xff09;&#xff0c;也叫组装测试或联合测试。在单元测试的基础上&#xff0c;将所有模块按照设计要求&#xff08;如根据结构图&#xff09;组装成为子系统或系统&#xff0c;进行集成测试。 集成测试&#xff…

Java并发之互斥一:管程

1、简单聊聊什么是管程模型 &#xff08;共享资源&#xff09;&#xff1a;定义一个共享变量&#xff0c;可以理解锁&#xff0c;令牌这类的东西&#xff08;互斥访问共享资源&#xff09;&#xff1a;获取这个锁、令牌的时候是排好队的&#xff0c;只允许单线程访问&#xff…