Linux C编程之进程控制

目录

一,进程标识:

1,获取当前进程ID:    

二,进程控制:

1,进程的创建:

2,exec函数族:

3,终止进程

4,进程等待:


一,进程标识:

在linux系统中,每个进程被创建时会被分配一个数据结构,称为进程控制块(PCB),它用来记录进程的外部特征。进程与PCB是一一对应得关系。通常PCB包含有以下信息:进程标识符,进程当前状态,进程相应程序和数据地址,进程资源清单,进程优先级,进程同步与通信机制,CPU现场保护区,进程所在队列PCB连接字等。其中进程标识符又称为进程ID,它是一个非负整数,用来唯一的表示一个进程。Linux系统中有专用的进程,进程ID 0是调度进程,常被称为交换进程,ID 0是init进程。

 ps -aux      //shell命令查看当前进程详情信息

 如下所示,其中PID就是进程ID。

1,获取当前进程ID:    

#include <sys/types>

#include <unistd.h>

pid_t getpid(void);      //返回当前进程ID

实例如下: get_pid.c

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

int main()
{
   printf("The current process ID is %d",getpid());
   return 0;

}

 运行结果如下,返回当前进程ID:

二,进程控制:

1,进程的创建:

#include <sys/types>

#include <unistd.h>

pid_t fork(void);  

fork函数用于派生出一个进程,若成功,父进程返回子进程得进程ID,子进程返回0,出错则返回-1。成功执行时,fork会返回两次。fork函数调用的作用是复制一个进程,由fork创建出得进程称为子进程,子进程从父进程得到了数据段和堆栈段得复制,并分配新的内存。对于只读代码段,通常使用共享内存的方式访问。

示例如下,fork函数创建一个进程:fork.c

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

int main()
{
 int count=0;
 pid_t pid;
 pid=fork();    //此时有两个进程同时运行
 if(pid<0)
 {
    printf("some error!\n");
	exit(1);
 }
 else if(pid==0)   //子进程
 {
  printf("This is child process! and ID is %d\n",getpid());
 }
 else             //父进程
 {
   printf("This is parent process,and ID is %d\n ",getpid());
 }
return 0;

}

运行结果如下: 

#include <sys/types>

#include <unistd.h>

pid_t vfork(void);  

vfork()函数于fork函数类似,但区别在于:vfork无需全部复制父进程的数据段,在子进程进程未调用exec或exit函数之前,父子进程共享数据段,vfork函数中子进程先运行,父进程挂起,直到子进程运行到exit或exec后,父子进程执行次序不在有限制。严格意义上讲,vfork创建的只是线程,没有独立得内存资源。

2,exec函数族:

fork()函数创建的子进程和父进程几乎完全相同,要改变子进程,执行另一个程序,利用以下函数:

#include <unistd.h>

int execl(const char *pathname,const char *arg,...);

int execlp(const char *filename,const char *arg,...);

int execle(const char *pathname,const char *arg,...,char *const envp[]);

int execv(const char *pathname,char *const argv[]);

int execvp(const char *filename,char *const argv[]);

int execve(const char *pathname,char *const argv[],char *const envp[]);

六个函数若成功无返回,出错返回-1。

函数名含有" l",其参数个数不定,参数由所调用程序命令行列表组成,最后以NULL结束。

函数名含有" v",使用字符串数组指针argv指向参数列表,同含" l"类似,最后以NULL结束。

函数名含有"p"的自动在环境变量PATH指定的路径中搜索要执行的程序,故其第一个参数为filename.。

函数名含有"e"的,其参数envp是一个字符串数组指针,用于指定环境变量,可以有用户自定设置子进程的环境变量,envp数组也要以NULL结尾。

exce函数族作用是根据指定文件名找到可执行文件,并用它取代调用进程的内容,就是在调用进程内执行一个可执行文件,该文件可以是二进制文件也可以是脚本文件。

示例如下:exec.c

#include <stdio.h>
#include <unistd.h>
/*
  echo 命令打印紧跟的命令行参数
  env 查看所有的环境变量
*/


int main()
{
char *envp[]={"PATH=/tmp","USER=root","STATUS=testing",NULL};
char *argv_execv[]={"echo","excuted by execv","NULL"};
char *argv_execvp[]={"echo","excuted by execvp","NULL"};
char *argv_execve[]={"env","NULL"};
if(fork()==0)
{
if(execl("/usr/bin/echo","echo","excuted by excel",NULL))
		perror("Err on excel\n");   //perror出错时,把出错原因输出到标准错误
}
if(fork()==0)
{
if(execlp("echo","echo","excuted by execlp",NULL))
		perror("Err on execlp\n");
}

if(fork()==0)
{
if(execle("/usr/bin/env","echo","excuted by excele",NULL,envp))
		perror("Err on excele\n");
}

if(fork()==0)
{
if(execv("/usr/bin/echo",argv_execv))
		perror("Err on excev\n");
}
if(fork()==0)
{
if(execvp("echo",argv_execvp))
		perror("Err on excevp\n");
}	
if(fork()==0)
{
if(execve("/usr/bin/env",argv_execve,envp))
		perror("Err on execve\n");
}
return 0;
}

3,终止进程

#include <stdlib.h>

void exit(int status);   

statu为进程结束时的状态,一般0标识没有意外的正常结束。

4,进程等待:

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *status)

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

成功返回进程ID,出错返回-1。在调用exit后,进程并非完全消失,还留下了一个称为僵尸进程的数据结构,此时,要完全销毁掉该进程,调用wait函数立即阻塞自己,直到找到该僵尸进程并销毁它。可以是进程组之间的等待,也可以是父进程对子进程的等待。

status保存被收集进程退出时的状态。一般不关心直接取NULL。

waitpid函数参数pid等待指定进程:pid>0时,等待进程ID为pid的进程,pid=0时,等待同一进程组任意子进程,pid=-1,等待任意子进程退出,pid<-1,等待指定进程组任意子进程,指定进程组ID为pid绝对值,options可选参数为WNOHANG时,即使无子进程退出,他不会一直等待,会立即返回。

实例代码如下:  wait.c

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

int main()
{
   pid_t pc,pr;
   if((pc=fork())<0)
   {
   printf("some error\n");
   exit(1);
   }
   if(pc==0)
   {
    printf("This is child process,ID is %d\n",getpid());
    sleep(5);   //睡眠5s
   }
   else
   {
   pr=wait(NULL);  //等待子进程苏醒过来,才会执行
   printf("Catch the child's ID is %d\n",pr);
    
   }

   return 0;

}

 观察到第一句显示到频幕上后,间隔5秒后,第二句才显示:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值