Linux下C语言中进程的创建与回收

进程的概念

程序

存放在磁盘上的指令和数据的有序结合(文件);

静态的。

进程

执行一个程序所分配的资源的总称;

进程是程序的一次执行过程;

动态的,包括创建、调度、执行和消亡。

进程类型

交互进程:在shell下启动。以在前台运行,也可以在后台运行

批处理进程:和在终端无关,被提交到一个作业队列中以便顺序执行

守护进程:和终端无关,一直在后台运行

进程常用命令

查看进程信息

ps     查看系统进程快照

top    查看进程动态信息

/proc  查看进程详细信息

ps 命令详细参数:

-e:显示所有进程

-l:长格式显示更加详细的信息

-f 全部列出,通常和其他选项联用

表头

含义

F

进程标志,说明进程的权限,常见的标志有两个:

  • 1:进程可以被复制,但是不能被执行;
  • 4:进程使用超级用户权限;

S

进程状态。进程状态。常见的状态有以下几种:

  1. -D:不可被唤醒的睡眠状态,通常用于 I/O 情况。
  2. -R:该进程正在运行。
  3. -S:该进程处于睡眠状态,可被唤醒。
  4. -T:停止状态,可能是在后台暂停或进程处于除错状态。
  5. -W:内存交互状态(从 2.6 内核开始无效)。
  6. -X:死掉的进程(应该不会出现)。
  7. -Z:僵尸进程。进程已经中止,但是部分程序还在内存当中。
  8. -<:高优先级(以下状态在 BSD 格式中出现)。
  9. -N:低优先级。
  10. -L:被锁入内存。
  11. -s:包含子进程。
  12. -l:多线程(小写 L)。
  13. -+:位于后台。

UID

运行此进程的用户的 ID;

PID

进程的 ID;

PPID

父进程的 ID;

C

该进程的 CPU 使用率,单位是百分比;

PRI

进程的优先级,数值越小,该进程的优先级越高,越早被 CPU 执行;

NI

进程的优先级,数值越小,该进程越早被执行;

ADDR

该进程在内存的哪个位置;

SZ

该进程占用多大内存;

WCHAN

该进程是否运行。"-"代表正在运行;

TTY

该进程由哪个终端产生;

TIME

该进程占用 CPU 的运算时间,注意不是系统时间;

CMD

产生此进程的命令

top    查看进程动态信息

shift +> 后翻页

shift +< 前翻页

top -p PID  查看某个进程

改变进程优先级

nice   按用户指定的优先级运行进程

     nice [-n NI值] 命令

  • NI 范围是 -20~19。数值越大优先级越低
  • 普通用户调整 NI 值的范围是 0~19,而且只能调整自己的进程。
  • 普通用户只能调高 NI 值,而不能降低。如原本 NI 值为 0,则只能调整为大于 0。
  • 只有 root 用户才能设定进程 NI 值为负值,而且可以调整任何用户的进程。

renice   改变正在运行进程的优先级

renice [优先级] PID

jobs   查看后台进程

bg     将挂起的进程在后台运行

fg      把后台运行的进程放到前台运行

ctrl+z  把运行的前台进程转为后台并停止。

./test &  把test程序后台运行


子进程概念

子进程为由另外一个进程(对应称之为父进程)所创建的进程

子进程创建-fork

#include  <unistd.h>  

pid_t  fork(void);

  • 创建新的进程,失败时返回-1
  • 成功时父进程返回子进程的进程号,子进程返回0
  • 通过fork的返回值区分父进程和子进程

要点:

1.子进程只执行fork之后的代码

2.父子进程的执行顺序是操作系统决定的

3.子进程继承了父进程的内容

4.父子进程有独立的地址空间,互不影响

5.若父进程先结束  

  • 子进程成为孤儿进程,被init进程收养  
  • 子进程变成后台进程

6若子进程先结束  

  • 父进程如果没有及时回收,子进程变成僵尸进程

进程创建 – fork – 示例

#include <stdio.h>
#include <unistd.h>

int main(int argc,char **argv){
    
    pid_t pid;
    printf("before fork\n");
    pid = fork();
    if(pid>0){
       printf("This is father process\n");
       printf("pid=%d\n",(int)pid);
       printf("father after fork\n");
       while(1){
         sleep(1);
         printf("father sleep\n");
       }
   }else if(pid==0){
       printf("This is child process\n");
       printf("pid=%d\n",(int)pid);
       printf("child after fork\n");
       while(1){
          sleep(1);
          printf("child sleep\n");
       }
    }else if(pid<0){
       perror("fork");
       return 0;
    }
   // printf("pid=%d\n",(int)pid);
  //  printf("after fork\n");
 
}

进程结束 – exit/_exit

 #include <stdlib.h>  

#include  <unistd.h>  

void  exit(int  status);  

void  _exit(int  status);

void  _Exit(int  status);

  • 结束当前的进程并将status返回
  • exit结束进程时会刷新(流)缓冲区

进程返回值和结束方式

子进程通过exit / _exit / return 返回某个值(0-255) 父进程调用wait(&status) 回收  WIFEXITED(status)                      判断子进程是否正常结束

WEXITSTATUS(status)                  获取子进程返回值

WIFSIGNALED(status)                  判断子进程是否被信号结束

WTERMSIG(status)                       获取结束子进程的信号类型


进程回收-wait

 #include <sys/wait.h>  

pid_t wait(int *status);  

  • 成功时返回回收的子进程的进程号;
  • 失败时返回EOF  若子进程没有结束,父进程一直阻塞  
  • 若有多个子进程,哪个先结束就先回收  
  • status 指定保存子进程返回值和结束方式的地址  
  • status为NULL表示直接释放子进程PCB,不接收返回值
  • 子进程结束时由父进程回收
  • 孤儿进程由init进程回收
  • 若没有及时回收会出现僵尸进程

进程回收-waitpid

 #include  <sys/wait.h>  

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

  • 成功时返回回收的子进程的pid或0;
  • 失败时返回EOF  
  • pid可用于指定回收哪个子进程或任意子进程  
  • status指定用于保存子进程返回值和结束方式的地址  
  • option指定回收方式,0 或 WNOHANG

进程回收 – waitpid – 示例

waitpid(pid, &status, 0);

waitpid(pid, &status, WNOHANG);

waitpid(-1, &status, 0);

waitpid(-1, &status, WNOHANG);

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char** argv){

   pid_t pid;
   pid_t rpid;
   pid = fork();
   int status;
   if(pid<0){
      perror("fork");
      return 0;
   }
   else if(pid == 0){
       sleep(10);
       printf("child will exit\n");
       exit(2);

   }else if(pid >0){
       //rpid = wait(&status);
       sleep(20);
       waitpid(-1,&status,WNOHANG);
       printf("Get child status=%x\n",WEXITSTATUS(status));
   }

   while(1){
     sleep(1);
   }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以给你介绍一下C语言实现父进程猜拳游戏的代码。以下是一个简单的示例: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #define ROCK 0 #define PAPER 1 #define SCISSORS 2 int main() { int parent, child; int parent_choice, child_choice; // 创建进程 child = fork(); if (child < 0) { printf("无法创建进程\n"); exit(1); } else if (child == 0) { // 子进程逻辑 srand(time(NULL)); child_choice = rand() % 3; // 随机生成子进程的选择 exit(child_choice); // 子进程退出,并将选择作为退出码返回给父进程 } else { // 父进程逻辑 printf("欢迎来到猜拳游戏!\n"); printf("请输入你的选择(0-石头,1-剪刀,2-布):"); scanf("%d", &parent_choice); // 等待子进程退出,并获取子进程的选择 wait(&parent); child_choice = WEXITSTATUS(parent); printf("你的选择:%d\n", parent_choice); printf("对手的选择:%d\n", child_choice); // 判断胜负 if (parent_choice == child_choice) { printf("平局!\n"); } else if ((parent_choice == ROCK && child_choice == SCISSORS) || (parent_choice == PAPER && child_choice == ROCK) || (parent_choice == SCISSORS && child_choice == PAPER)) { printf("你赢了!\n"); } else { printf("你输了!\n"); } } return 0; } ``` 这段代码实现了一个简单的猜拳游戏,父进程和子进程分别选择石头、剪刀或布,然后判断胜负并输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值