进程(详解)

本文详细介绍了Linux下如何创建进程,使用makefile和grep命令查看进程,以及如何通过kill命令终止进程。重点讨论了fork函数,包括其返回值的意义以及为何会返回两次。同时,探讨了进程的ppid(父进程ID)以及进程间的代码和数据共享。最后,解释了fork函数在操作系统层面如何工作,以及子进程如何继承父进程的属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.怎么创建进程

创建mytest.c文件
输入下列代码

#include<stdio.h>
#include<unistd.h>
int main()
{
  while(1)
  {   
     printf("I am  a process!\n");
     sleep(1); 
  }
  return 0;
}

创建makefile文件输入下列代码

mytest:mytest.c
		gcc -o mytest mytest.c
.PHONY:clean
clean:
		rm -f mytest

我们make一下,在把生成可执行程序mytest执行,那么mytest这个时候就是进程了
在这里插入图片描述

2.怎么查看进程

在这里插入图片描述
不过上面的那个grep是什么意思,那个其实是命令,我们使用过的命令,会自动变成一个个进程
不过要是不想显示grep也可以
在这里插入图片描述
grep -v grep的意思是匹配到grep就不显示,把没匹配到grep的给显示出来
而通过了解了linux的进程,windows的进程也了解,像打开游览器其实就是在打开一个进程

不过上面打印的那些东西看不懂,怎么办
打开下面命令

ps axj | head -1 && ps axj | grep mytest | grep -v grep

在这里插入图片描述
上面的pid其实就是进程id了,那么我们就去存在进程id的文件proc里面查找一下这个id
在这里插入图片描述
可以看到确实存在这个id
这个时候我们把可执行文件mytest暂停再执行,这个时候我们的进程id就变了,相当于创建了一个新的进程
我们输入ls /proc/进程号 -al
在这里插入图片描述
上面的exe代表着是进程对应的可执行程序的磁盘文件
上面的cwd代表着进程当前的工作路径

不过这样子查pid太浪费时间了
我们其实可以写代码来知道当前进程的进程id
改下之前写的mytest.c
在这里插入图片描述
可以看到pid一模一样
在这里插入图片描述

3.杀掉进程命令

输入kill -9 进程id,就可以向进程发出信号9的信号从而杀掉进程
在这里插入图片描述

4.进程的ppid

ppid其实就是父进程的id
获取ppid
代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
  while(1)
  {   
     printf("I am  a process! pid:%d ppid:%d\n",getpid(),getppid());
     sleep(1); 
  }
  return 0;
}

在这里插入图片描述
再看这里我期间把进程给暂停了,又重新打开,发现pid变了但是父进程id没变
在这里插入图片描述
我们查看一下父进程,从下面图片可以看到父进程是一个bash的东西
在这里插入图片描述
所以我们从这里看到几乎我们在命令行执行的所有命令,都是bash进程的子进程

5.fork函数

fork函数是用来创建子进程的,所以它会有二个返回值
如果成功了 父进程返回子进程的pid,给子进程返回0

我们来检验一下是不是真的,下面代码按我们上面讲的,他可能会打印二次

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
  pid_t id = fork();

  printf("hello fork\n");
  return 0;
}

可以看到确实打印了二次
在这里插入图片描述
不过这个打印的太乱了,我们加个sleep(1);
在这里插入图片描述
除了这个还有一个奇怪的就是它们的pid

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
  pid_t id = fork();

  printf("hello fork id:%d\n", id);

  sleep(1);
  return 0;
}

打印结果,一个是2672一个是0
在这里插入图片描述
那么我们再来检验下面代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
  pid_t id = fork();
  if(id == 0)
  {
        //child
        while(1)
        {
            printf("我是子进程,我的pid: %d,我的父进程是: %d\n", getpid(), getppid());
            sleep(1);
        }
  }
  else
  {
        //parent
        while(1)
        {
            printf("我是父进程,我的pid: %d,我的父进程是: %d\n", getpid(), getppid());
            sleep(1);
        }
  }
  return 0;
}

按照C语言if和else是不会同时执行的,而且也不会出现二个死循环的
但是我们在linux执行上面代码来看看
在这里插入图片描述
上面的32716是base进程的id
可以看到出现了问题了子进程和父进程同时执行并死循环
因为fork以后,父进程和子进程会共享代码,一般都会执行之后的代码,所以才会打印二次的问题
fork以后,会有不同的返回值,可以通过不同的返回值,可以让父子进程执行不同的代码

1. fork()为什么给父进程返回子进程的pid,给子进程返回0

因为一个父亲可以有很多个儿子,但是儿子只有一个父亲,干爹除外,所以父进程必须要有标识子进程的方式,fork以后给父进程返回子进程的pid
子进程最重要的是知道自己被创建成功了,因为子进程找父进程的代价特别低,因为只有一个父进程,不像父进程找子进程

2.为什么fork会返回二次

fork是个函数,是由操作系统调用的 那么fork之后操作系统做了什么?
进程理论上是操作先描述再组织是父进程创建了,那么父进程是不是进程是的
那么怎么证明操作系统多了个进程,在操作系统里面等于 task_struct + 子进程和数据,子进程的task_struct是个对象,那么子进程里面的pid ppid它是怎么来的,基本上都是由父进程继承下来的,也可以说是拷贝下来的
那么这里又有一个问题,子进程的代码从哪里来,他没有从哪里来只是和父进程共用一份,这就是fork之后,父子进程代码共享,但是数据是各自独立的,所以可以通过不同的返回值来,让父子进程分别实现不同的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值