当前位置: 首页 > article >正文

进程相关(创建-回收-exec-守护进程)

1.进程的创建与回收

1.1创建

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

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

	if( pid < 0 ){
		perror( "fork" );
		return 0;
	}else if( 0 == pid){
		printf( "这是子进程!\n" );
	}else{
		printf( "这是父进程!\n" );
	}
}

1.2 回收子进程

wait( &status );

阻塞回收,WEXITSTATUS(status)

成功时返回回收的子进程的进程号;失败时返回EOF

若子进程没有结束,父进程一直阻塞

若有多个子进程,哪个先结束就先回收

status 指定保存子进程返回值和结束方式的地址

status为NULL表示直接释放子进程PCB,不接收返回值

#include  <unistd.h>
  pid_t waitpid(pid_t pid, int *status, int option);

参数:

pid
pid>0时,等待该pid的子进程结束,不管其它子进程。

pid=-1时,等待任意子进程退出,此时waitpid和wait的作用相同。

pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。

pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。

options

options提供了一些额外的选项来控制waitpid,目前在Linux中只支持

WNOHANGWUNTRACED两个选项,

这是两个常数,可以用"|"运算符把它们连接起来使用

WNOHANG :若由pid指定的子进程未发生状态改变(没有结束),则waitpid()不阻塞,立即返回0

WUNTRACED: 返回终止子进程信息和因信号停止的子进程信息

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

int main()
{
	int status;
	pid_t pid = fork();

	if( pid < 0 ){
		perror( "fork" );
		return 0;
	}else if( 0 == pid){
		printf( "这是子进程!\n" );
		exit( 0 );
	}else{
		printf( "这是父进程!\n" );
		//wait( &status );阻塞回收
		int rpid = waitpid( -1, &status, WNOHANG );
		printf( "子进程返回状态值status = %x \n", WEXITSTATUS(status) );
	}
	
	return 0;
}

2.exec函数族与守护进程

2.1 exec函数族

背景:
fork创建子进程之后,

子进程和父进程执行相同的代码,

但是在实际开发中,我们希望父子进程执行不同的代码。

作用:执行指定的程序

#include  <unistd.h>
  int execl(const char *path, const char *arg,);
  int execlp(const char *file, const char *arg,);

成功时执行指定的程序;失败时返回EOF

path 执行的程序名称,包含路径

arg… 传递给执行的程序的参数列表

file 执行的程序的名称,在PATH中查找

两个函数区别:
execlp不需要写文件名全路径,在PATH查找

最后一个参数必须用空指针(NULL)作结束

进程当前内容被指定的程序替换,但进程号不变

第0个参数必须要写,虽然它没有使用

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

int main(int argc, const char *argv[])
{
	pid_t child1, child2, child;
	//创建两个子进程
	child1 = fork();
	child2 = fork();

	//子进程1的出错处理
	if(-1 == child1){
		perror("1 fork error");
		exit(1);
	}else if(0 == child1){                    //子进程1中执行其他程序
		printf("调用execlp(),执行ls -l\n");
		if(execlp("ls", "ls", "-l", NULL) < 0){
			printf("child1 execlp error\n");
		}
	}

	//子进程2的出错处理
	if(-1 == child2){
		perror("child2 fork error");
		exit(1);
	}else if(0 == child2){                //子进程2中执行其他程序
		printf("暂停5秒\n");
		sleep(5);
		exit(0);
	}else{
		printf("在父进程中等待两个子进程的退出\n");
		child = waitpid(child1, NULL, 0);//非阻塞等待
		if(child == child1){             //进程1退出
			printf("Get child1 exit code\n");		
		}else{
			printf("error!\n");
		}

		do
		{
			child = waitpid ( child2, NULL, WNOHANG ) ;//非阻塞式等待,需要循环等待
			if ( child == 0 ){
				printf("子进程2还未结束\n");
				sleep(1);
			}
		}while ( 0 == child);

		if ( child == child2 ){
			printf("Get child2 exit code\n");
		}else{
			printf("Error!\n");
		}
	}
		exit ( 0 ) ;
}

2.2 守护进程

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

int main ()
{
	FILE* fp;
	time_t t;

	pid_t pid = fork();
	if( pid < 0 ){
		perror("fork");
		return 0;
	}
	//1.创建子进程,父进程退出
	else if( pid > 0 ){
		exit( 0 );
	}
	printf("\nbefore setsid:sid=%d pid=%d gpid=%d\n", 
			getsid( getpid() ), getpid(), getpgid( getpid() ) );
	//2.设置sid
	if( setsid() < 0 ){
		perror("setsid");
		exit( 0 );
	}
	printf("after setsid:sid=%d pid=%d gpid=%d\n", 
			getsid( getpid() ), getpid(), getpgid( getpid() ) );
	//3.更改工作目录
	chdir("/tmp");

	//4.设置文件掩码
	if( umask(0) < 0 ){
		perror("umask");
		exit(0);
	}
	//5.关闭文件描述符
	close(0);
	close(1);
	close(2);

//打开文件time.log
	if( (fp = fopen("time.log" , "a")) == NULL){
		perror("fopen");
		exit(-1);
	}

	while(1){
		time( &t );
		fprintf( fp, "%s", ctime(&t) );
		fflush( fp );
		sleep(1);
	}
	return 0;
}
time() 函数:
		获取系统当前的时间,返回一个以秒为单位的整数值。
ctime() 函数:
		将time_t 类型的时间值转换为一个字符串,
		函数返回的字符串是一个指向静态分配缓冲区的指针。
fprintf() 函数:
		将格式化的数据写入文件或流中
fflush() 函数:
		将缓冲区中的数据写入文件或流中。	
sleep() 函数:
		使进程挂起指定的时间,以秒为单位。

http://www.kler.cn/news/16398.html

相关文章:

  • 【华为OD机试 2023最新 】任务总执行时长(C语言题解 100%)
  • BPMN2.0 任务-服务任务
  • LVS负载均衡集群--DR模式
  • Chapter1:控制系统数学模型(下)
  • LC-1033. 移动石子直到连续(分类讨论)
  • Ubuntu搜狗输入法安装指南
  • Redis入门指南:深入了解这款高性能缓存数据库
  • MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库
  • [AION]我眼中的《永恒之塔私服》
  • 【拓扑排序】课程表系列
  • 基于SpringBoot的冬奥会科普平台
  • Python进阶项目--只因博客(bootstrap+flask+mysql)
  • Threejs进阶之十二:Threejs与Tween.js结合创建动画
  • 【001-Java基础练习】-适合初学者的练习
  • SPSS如何制作基本统计分析报表之案例实训?
  • 青少年软件编程(C语言) 等级考试试卷(五级)2021年12月
  • 【MySQL入门指南】外键约束使用详解
  • 服务器性能调优
  • 理解什么是sql注入攻击 + xss攻击 + cors 攻击
  • 吴恩达 Chatgpt prompt 工程--1.Guidelines
  • 每日一题137——删除链表的节点
  • Nginx反向代理和负载均衡
  • 回炉重造十一------ansible批量安装服务
  • Java IO流第一章
  • “BIM+智慧工地”精准“数字化”变身智慧工程“管家”
  • 国内首款多节点/无需密钥/无需登录的ChatGPT客户端开源项目
  • v2c - 从Verilog 转换到 C语言的工具
  • DDS基本原理与FPGA实现
  • 19安徽比赛
  • `netstat`的替换命令`ss`