关于进程控制

1.首先是创建进程
fork/vfork
vfork在fork引入后就被淘汰了
开一下虚拟机,man一下fork

#include <unistd.h>

       pid_t fork(void);

子进程返回0,
父进程返回的是子进程的pid
失败返回-1

int main( void )
{
   pid_t pid;
   printf("Before: pid is %d\n", getpid());
   int pid = fork()
   if ( pid < 0) {
	   perror("fork()");
	   return -1;
	   }else
   			printf("After:pid is %d, fork return %d\n", getpid(), pid);
   sleep(1);
   return 0;
}

运行结果首先打印之前的pid,然后创建子进程后打印出两个进程id,父进程返回子进程ID,但是子进程没有打印Before,因为在fork之前父进程独立执行,在fork之后,父子分别执行,谁先执行由调用器决定,如果想让子进程先执行,可以让父进程先睡会.
在程序的虚拟空间哪里也说过,进程创建的写时拷贝技术,子进程复制父进程,指向的物理内存也是一样的,数据改变了以后,在分配新的

创建子进程有两个作用
(1).父进程希望一个除了执行代码段不同,其他都相同的子进程来执行不同的代码段
(2).一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数 函数替换接下来说

2.进程退出
在printf函数中,"\n"会刷新缓冲区
return
main中的return才是退出进程,其他函数的return是退出函数
退出前刷新缓冲区
exit

void exit(int status); //这是一个库函数,       退出前刷新缓冲区

_exit

	void _exit(int status); //这是一个系统调用接口 不会刷新缓冲区,缓冲区数据被丢弃

就是说exit函数在退出前的操作更多

int main()
{
   printf("hello");
   exit(0);
}

会输出hello

int main()
{
   printf("hello");
   _exit(0);
}

不会输出

3.进程等待
进程等待是十分必要的,这预防了僵尸进程的出现
等待子进程的状态改变(等待子进程退出)—获取子进程的退出返回值

等待有两个函数

pid_t wait(int* status);

wait接口功能是一直等待任意一个子进程退出,子进程退出后,获取到返回值,放到传入的参数status中,不感兴趣可以置NULL
这是一个阻塞接口,没有等待到子进程会阻塞并一直阻塞下去
返回值:
成功返回被等待进程pid,失败返回-1.
父进程会阻塞在wait,等待子进程退出

第二个是

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

pid = -1 等待任意一个子进程 pid > 0: 等待指定子进程
status中低16位中的高8位存储子进程返回值,低8位中的高1位存储coredump(核心转储)标志,低7位存储异常退出信号值,若为0,表示没有异常信号,表示程序正常退出
status是输出型参数,由操作系统填充,置NULL表示不关心子进程退出状态信息
若非0,表示程序异常退出,返回值不具有意义
options(选项标志) WNOHANG: 将waitpid设置成非阻塞 0默认阻塞
返回值
若WNOHANG被指定,没有子进程退出则立即报错返回0;错误:-1

int main()
{
 pid_t pid;
 pid = fork();
 if(pid < 0){
   printf("%s fork error\n",__FUNCTION__);
   return 1;
 } else if( pid == 0 ){ //子进程
   printf("child is run, pid is : %d\n",getpid());
   sleep(5);//休眠5秒,更好的观察等待
   exit(257);
 } else{
   int status = 0;
   pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5S
   printf("this is test for wait\n");
   if( WIFEXITED(status) && ret == pid )//这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。
   {
	 printf("等待成功, 子进程返回:%d.\n",WEXITSTATUS(status));
 }else{
	 printf("wait child failed, return.\n");
	 return 1;
 }
 }
 return 0;
}

下面是非阻塞式等待

int main()
{
   pid_t pid;//定义 pid
    
   pid = fork();//获取返回值
   if(pid < 0){
       printf("%s fork error\n",__FUNCTION__);
       return 1;
   }else if( pid == 0 ){ //子进程
       printf("child is run, pid is : %d\n",getpid());
       sleep(5);/睡5秒方便观察退出
       exit(1);
   } else{
       int status = 0;//初始化status
       pid_t ret = 0;
       do
       {
           ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待,接受返回值,option设置非阻塞等待
           if( ret == 0 ){
               printf("child is running\n");/返回值为0,子进程正在运行
           }
           sleep(1);
       }while(ret == 0);//循环回去判断
    
       if( WIFEXITED(status) && ret == pid ){//判断子进程是否为正常退出的,正常退出这个红返回1
           printf("wait child 5s success, child return code is
:%d.\n",WEXITSTATUS(status));//正常退出
       }else{
           printf("wait child failed, return.\n");//等待失败
           return 1;
       }
   }
   return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值