linux 系统编程实验(四)

  1. 实验目的
  1. 理解进程的概念
  2. 掌握进程复制函数fork的用法
  3. 掌握替换进程映像exec函数族
  4. 掌握守护进程的创建步骤和使用。

1.用进程相关API 函数编程一个程序,使之产生一个进程扇:父进程产生一系列子进程,每个子进程打印自己的PID 然后退出。要求父进程最后打印PID。

这个实验让我深刻了解操作系统创建进程的模样,操作系统创建进程是以树的形式创建的 。以某个存在的进程作为树根开始,一级一级往下创建。实验如图:

仔细看好进程id,这是bash的进程号。

如图,以当前执行的bash为根,为可执行文件创建的子进程号为8239(这里可以当作第一父进程,实际上最顶级的进程号是bash进程),接着8239又创建了8240,8241这两个子进程,然后8240 又创建了8242子进程。

  这就是一个进程树,而且通常新创建的pid都是加一的。

实验中使用wait是让父进程先暂时阻塞,等待子进程的结束,收集子进程执行信息/状况。具体可参考博客:

https://www.cnblogs.com/king-77024128/articles/2684317.html

加个exit的区别,参考    https://www.cnblogs.com/dongguolei/p/8098181.html

2.用进程相关API 函数编写一个程序,使之产生一个进程链:父进程派生一个子进程后,然后打印出自己的PID,然后退出,该子进程继续派生子进程,然后打印PID,然后退出,以此类推。

递归写法:

逆序打印:逆序打印的思路和平常打印不同,要做到逆序就需要让每个父进程要保持住不能让它退出,如图:

当p1生出p2的时候,p1作为父亲不能退出,然后p2作为父亲生出p3,同理p2作为父亲也要保持住,这样等p3退出时,作为父亲的进程全部打印自己的pid,挨个退出,这样就形成了逆序。

实验结果:

可以看到,一旦设置了阻塞,那么充当父进程后暂时是阻塞的,这就是为什么按下三次回车才有结果显示,当最后一个进程只作为孩子的时候,还是要跑一次代码,所以需要再输入3,但最后一个进程将不执行循环的代码,直接退出(i的值是3不符合循环条件),子进程退出,立马呈现结果。

3.编写程序execl.c,实现父进程打印自己的pid号,子进程调用execl函数,用可执行程序file_creat替换本进程。注意命令行参数。

/*execl.c*/
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
/*判断入参有没有传入文件名*/
	if(argc<2)
	{
	    perror("you haven,t input the filename,please try again!\n");
		exit(EXIT_FAILURE);
	
	}
	pid_t result;
	result=fork();
	if(result>0)
{
		printf(“I’m parent,my pid:%d, mysun’s pid %d\n”,getpid(), result);

}
/* 下面代码是调用ls程序, 用可执行程序ls替换本进程
	if(result==0)
	{
		printf(“I’m sum process my pid is %d\n”,getpid());	
		if(execl("/bin/ls","ls","-l",NULL)<0)
		{
			perror("execlp error");
		}
	}*/
	/*下面程序调用execl函数,用可执行程序file_creat替换本进程*/
if(result==0)
{
	printf(“I’m sum process my pid is %d\n”,getpid());		if(execl("./file_creat","file_creat",argv[1],NULL)<0)
		perror("execl error!");
}
}

其中file_creat.c的 代码如下:
file_creat.c
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 

void  create_file(char *filename)
{ 
    /*创建的文件具有可读可写的属性*/	
    if(creat(filename,0666)<0)
	{ 
        printf("create file %s failure!\n",filename); 
        exit(EXIT_FAILURE); 
    }
	else
	{ 
        printf("create file %s success!\n",filename); 
    } 
} 

int main(int argc,char *argv[])
{ 
    /*判断入参有没有传入文件名 */
   	if(argc<2)
	{
        perror("you haven't input the filename,please try again!\n"); 
        exit(EXIT_FAILURE); 
    } 
	create_file(argv[1]);    
	exit(EXIT_SUCCESS); 
}

      

    

4.编写守护进程,参考守护进程模版代码daemon.c,实现每隔2秒中向系统日志文件/var/log/syslog中写入字符串“I am a daemonAAA!”,可使用下面的接口函数:

 openlog("daemon_test", LOG_CONS | LOG_PID, LOG_DAEMON);

syslog(LOG_DAEMON, "I am a daemonAAA!");

创建步骤:

1)父进程中执行fork后,执行exit退出;

2)在子进程中调用setsid;(脱离控制台)

3)让根目录“/”成为子进程的工作目录;

4)把子进程的umask变为0;

5)关闭任何不需要的文件描述符。

守护进程创建成功。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值