一、例程功能描述和代码思路
① 功能描述
将要浏览显示的文件内存 通过 管道 传输到 分页程序(more)中直接分页显示。
② 代码思路
第一步:通过main传参 传递 要浏览的文件路径
第二步:fopen打开该文件
第三步:创建无名管道
第四步:创建子进程
第五步:
父进程 循环 读取 文件中的数据,并且写到 管道中
子进程 使继承父进程的标准输入称为管道的读端
使用exec调用more程序去管道读端获取文本数据并且显示
注意虽然子进程调用exec,该子进程进程完全由新程序代换,替换原有进程的正文,但是之前的udp2的操作不受到影响。
③ 实例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#define DEF_PAGER "/bin/more" /*默认的系统分页程序*/
#define MAXLINE 20
struct demo_inf
{
FILE * fp;
int fd[2];
char file_line_data[MAXLINE];
int pid;
char *pager;
char * argv_process_name;
}DI;
void Pagination_Program(const char * obj_read_file);
void Pagination_Program(const char * obj_read_file)
{
DI.fp = fopen(obj_read_file,"r");
if(DI.fp == NULL)
{
perror("fopen ... ");
exit(-1);
}
if(pipe(DI.fd) < 0)
{
perror("pipe ... ");
exit(-1);
}
if((DI.pid = fork()) < 0)
{
perror("fork ... ");
exit(-1);
}
else if(DI.pid > 0)
{
/*父进程*/
memset(DI.file_line_data,0,MAXLINE);
while( fgets(DI.file_line_data,MAXLINE,DI.fp) != NULL)
{
if(write(DI.fd[1],DI.file_line_data,strlen(DI.file_line_data)) == -1)
{
perror("write ... ");
exit(-1);
}
memset(DI.file_line_data,0,MAXLINE);
}
if(ferror(DI.fp))
{
perror("ferror ... ");
exit(-1);
}
if(feof(DI.fp))
{
if(waitpid(DI.pid,NULL,0) < 0)
{
perror("waitpid ... ");
exit(-1);
}
exit(0);
}
}
else
{
/*子进程*/
if(DI.fd[0] != STDIN_FILENO)
{
if(dup2(DI.fd[0],STDIN_FILENO) != STDIN_FILENO)
{
perror("udp2 ... ");
exit(-1);
}
}
if((DI.pager = getenv("PAGER")) == NULL) // 获取分页系统MORE的环境变量路径
{
//perror("getenv error use default path");
DI.pager = DEF_PAGER;
}
//环境变量中截取more程序名字
if((DI.argv_process_name = strrchr(DI.pager,'/')) != NULL)
{
DI.argv_process_name++;
}
else
{
DI.argv_process_name = DI.pager; // 如果路径中没有/只能不需要切割
}
//调用exec启动more
if(execl(DI.pager,DI.argv_process_name,NULL) < 0)
{
perror("execl ... ");
exit(-1);
}
}
exit(0);
}
int main(int agrc, char ** argv)
{
if(agrc != 2)
{
printf("输入是没有指定文件!\n");
return -1;
}
Pagination_Program(argv[1]);
exit(0);
}
运行结果: