• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

XiaoXiaoli

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Linux编程_进程

目录

ps命令

进程标识符

进程的产生

多进程小案例 

进程的消亡和释放

 

ps命令

  ps命令用来查看进程相关信息,相关知识这里有介绍 https://www.cnblogs.com/Xiaoxiaogroup/p/14117133.html

进程标识符

  (1)ps命令显示的PID字段就是进程标识符。

  (2)进程标识符的类型为pid_t,该类型占位一般是有符号的16位整型数,大概有3万多个进程号。

  (3)进程标识号是顺次向下使用,即使之前被杀死的进程,其进程号也不再重复使用。

  (4)获取当前进程的进程号,使用函数getpid()。

  (5)获取当前进程的父进程进程号,使用函数getppid()。

进程的产生

  在学习多进程时,fork函数一定要理解透彻,理解父进程和子进程的关系才更深刻。

  fork函数原型,如下图。

  在当前进程中,使用fork函数创建子进程。

  fork函数的功能是复制[duplicating]一个新进程。这里对复制这个关键字要注意,复制意味着复制的进程和原来的进程一样,包括程序执行的位置也是一样。

  但是也有一些区别,复制出来的进程和原来的进程之间的区别,如:fork的返回值不同,父子进程的pid不同,ppid也不同。

  未决信号和文件锁不继承。资源利用量清0(父进程使用了大量资源,子进程清0)。

  这里还要注意一个进程init进程,init进程是所有进程的祖先进程,其进程号为1。

   这里通过几个程序来了解fork函数的使用。

  fork函数的返回值,fork函数执行一次,返回两个结果。

  如果创建成功,父进程中返回值为子进程的PID,子进程中返回值为0,父子进程返回的pid是不同的。

  如果创建失败,父进程中返回值为-1,子进程不会被创建。

  fork语句下面一定是分支语句,用来确定是父进程或子进程。

  程序执行结果。Begin一定是被打印一次,End分别被父进程和子进程各打印一次。

  这里需要强调,父进程和子进程谁先被调用取决于调度器的调度策略。

  如果想要子进程先被调用,最简单的方法是使用sleep函数让父进程睡眠一会。

  下面的运行结果是子进程先运行,将父进程睡眠了一会。

  使用ps axf 可以查看进程之间的关系,进程之间的阶梯状关系。

  当前shell创建了,process1进程,process1创建了子进程。

  进程实例2,代码如下。

  这里将fflush这行语句注释掉。

  使用下面的方式执行。

  可以看出Begin!该语句执行了2次。产生这个现象的根本原因是什么?

  在fork之前,fflush(NULL)刷新所有成功打开的流。终端是标准的输出设备,标准的输出设备默认是行缓冲模式\n可以刷新缓冲区。文件默认是全缓冲模式\n并不代表刷新缓冲区,代表换行。

  fork案例,筛选质数。

  单进程实现计算30000000---30000200之间的质数个数。使用宏定义数据区间。

  程序输出结果,可以看出计算的结果是顺序输出,结果是从小到大排列的。。

  查看程序所用的时间。

  time ./primer > /dev/null

  现在将当前程序改为多进程进行处理。

  程序代码,父进程的工作是产生200个整数,fork出200个子进程。fork出来的每一个子进程的任务是进行判断整数是否为质数。

  这里要注意,在子进程将任务执行完成后,需要将子进程退出,否则子进程将会产生新的子进程。

  程序的输出结果,此时程序输出的结果是无序的。

 

  使用 time,测试程序的执行时间。time ./primer1 > /dev/null

  接下来做的操作是让父进程先退出。此时子进程的状态为S,可中断的睡眠态,子进程的父进程为init。

  子进程为僵死态,一个僵尸态占用的资源很少,就是一个结构体,但是此时一个资源(pid)被占用。

  父进程创建子进程,父进程需要收尸子进程。如果父进程先结束,子进程还在执行,那么子进程马上变成了孤儿进程,被init接管,最后由init来收尸。

  所以在编程中需要注意,谁申请,谁释放,谁打开,谁关闭的原则。

进程的消亡及释放资源。

  进程回收主要涉及到wait和waitpid两个函数,等待进程的状态发生变化(wait for process to change state)。

  wait函数需要的参数是一个整型的地址,这里是将子进程收尸的状态放入到一个变量中。

  这里需要给其一个整型的地址空间。

  返回值,成功返回终止的子进程的id号,失败返回-1。

  这里的参数可以为NULL。整型值提供一些宏来给我们检测当前进程的退出状态.

  WIFEXITED 如果当前进程是正常终止,宏返回值为真。有5条正常终止,3条异常终止。exit _exit进程正常退出。

  WEXITSTATUS 进程正常退出的状态,返回进程正常退出的退出码,这个宏使用前提得保证进程正常退出,打印正常退出的状态码。

  WIFSIGNALED 如果当前子进程是一个信号终止的,这个宏返回值为真。

  WTERMSIG 这个宏可以打印打断进程的信号值。

  以上都是使用宏对整型值的状态进行检测,很多宏都是嵌套使用的。

  wait是没有指向的,没有指定收尸要收谁。

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

  waitpid好用的地方是options,它会一直等。

  WNOHANG 有了这个选项,将waitpid由阻塞变成了非阻塞。

  一个进程正常运行时,你要收尸无法收,该进程正在使用资源。

  waitpid的pid的值可以大于0,要收尸的子进程指定的。为0,收同组中任何的子进程。为-1,收任何一个子进程不是同组的也可以。<-1,进程组的任何一个进程。

   wait一定是阻塞的,waitpid可以不阻塞。

  将我们的程序添加一个wait操作。

 

  交叉分配法实现子进程完成任务。创建三个子进程完成200个待计算数的任务。

  程序执行结果。

 

posted on 2020-12-06 16:48  XiaoXiaoli  阅读(134)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3