第1章 Unix系统编程概述

操作系统用来管理所有资源,并将不同设备和不同的程序连接起来。

1.系统资源

处理器、输入输出(I/O)、进程管理、内存、设备、计时器、进程间通信、网络

2.Unix能做什么

(1)登入--运行程序--注销

(2)目录操作

(3)文件操作

3.编写more的实现

(1)more的作用

按下空格键,输出下一屏内容;

按下回车键,现实下一行内容;

按下q,结束显示。

(2)more的用法

more filename;

command | more;将命令的输出分页显示

more < filename;从标准输入获取要分页的内容

(3)第一版本more实现

/* more01.c 20190218 
 * read and print 24 lines then pause for a few special commands
 */
#include<stdio.h>
#include<stdlib.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE* );
int see_more();
int main(int argc, char* args[])
{
	FILE* fp;
	if(argc == 1)  /* not arg, use stdin*/
		do_more(stdin);
	else
		while(--argc)
		{
			if((fp = fopen(* ++args, "r")) != NULL)
			{
				do_more(fp);
				fclose(fp);
			}
			else
				exit(1);
		}
	return 0;
}

/* 
 * read PAGELEN lines, then call see_more() for further instrutions
 */
void do_more(FILE* fp)
{
	char line[LINELEN];
	int num_of_lines = 0;
	int reply;
	while(fgets(line, LINELEN, fp))
	{
		if(num_of_lines == PAGELEN)
		{
			reply = see_more();
			if(reply == 0)
				break;
			num_of_lines -= reply;
		}
		if(fputs(line, stdout) == EOF) /* show line*/
			exit(1);
		num_of_lines++;
	}	
}

/*
 *q means quit, space means PAGELEN, enter means one line
 */
int see_more()
{
	int c;
	printf("\033[7m more?\033[m");
	while((c=getchar()) != EOF)
	{
		if( c == 'q')
			return 0;
		if( c == ' ')
			return PAGELEN;
		if( c == '\n')
			return 1;
	}
}

(4)第二版程序实现

上面的more实现存在好几个问题:

a.q怎样不显示

b.如何不用回车程序就得到输入

c.如何去掉反白的more

d.使用ls  /bin | more01 会将more01的标准输入重定向到ls的标准输出,这样more01将从同一个数据流中读用户数据

解决前两个问题要用到第六章知识,将终端置位非缓冲和不回显模式。解决最后一个问题从标准输入得到要分页的数据,直接从键盘得到用户输入,即是文件/dev/tty。

/* more02.c 20190218
 * read and print 24 lines then pause for a few special commands
 * reads from /dev/tty for commands
 */
#include<stdio.h>
#include<stdlib.h>
#include<termios.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE* );
int see_more(FILE* );
void set_crmode();
void tty_mode(int);

int main(int argc, char* args[])
{
	FILE* fp;
	if(argc == 1)
		do_more(stdin);
	else
		while(--argc)
		{
			if((fp = fopen(* ++args, "r")) != NULL)
			{
				do_more(fp);
				fclose(fp);
			}
			else
				exit(1);
		}
	return 0;
}

/* 
 * read PAGELEN lines, then call see_more() for further instrutions
 */
void do_more(FILE* fp)
{
	char line[LINELEN];
	int num_of_lines = 0;
	int reply;
	FILE* fp_tty;

	tty_mode(0);  /* store tty mode */
 	set_crmode();
	fp_tty = fopen("/dev/tty", "r");
	if(NULL == fp_tty)
	{
		tty_mode(1); /* recover tty mode */
		exit(1);
	}
	while(fgets(line, LINELEN, fp))
	{
		if(num_of_lines == PAGELEN)
		{
			reply = see_more(fp_tty);
			if(reply == 0)
			{
				tty_mode(1);
				break;
			}
			num_of_lines -= reply;
		}
		if(fputs(line, stdout) == EOF) /* show line*/
		{
			tty_mode(1);
			exit(1);
		}
		num_of_lines++;
	}	
	tty_mode(1);
}

/*
 *q means quit, space means PAGELEN, enter means one line
 */
int see_more(FILE* cmd)
{
	int c;
	while((c=getc(cmd)) != EOF)
	{
		if( c == 'q')
			return 0;
		if( c == ' ')
			return PAGELEN;
		if( c == '\n')
			return 1;
	}
}

/*
 *purose: set file descriptor 0 into char-by-char and no echo mode
 */
void set_crmode()
{
	struct termios ttystate;
	int tty_fd = open("/dev/tty",O_RDWR);
	tcgetattr(tty_fd, &ttystate);
	ttystate.c_lflag &= ~ICANON; /* no buffering */
	ttystate.c_lflag &= ~ECHO;  /* no echo */
	ttystate.c_cc[VMIN] = 1;
	tcsetattr(tty_fd, TCSANOW, &ttystate);
	close(tty_fd);
}

void tty_mode(int how)
{
	static struct termios original_mode;
	int tty_fd = open("/dev/tty", O_RDWR);
	if(how == 0)
		tcgetattr(tty_fd, &original_mode);
	else
		tcsetattr(tty_fd, TCSANOW, &original_mode);
	close(tty_fd);
}

Linux命令:

ctrl + c: ( kill foreground process ) 发送 SIGINT 信号给前台进程组中的所有进程,强制终止程序的执行;

ctrl + z: ( suspend foreground process ) 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程,而并

            非结束进程,用户可以使用使用fg/bg操作恢复执行前台或后台的进程。fg命令在前台恢复执行被挂起的进

            程,此时可以使用ctrl-z再次挂起该进程,bg命令在后台恢复执行被挂起的进程,而此时将无法使用ctrl-z

            再次挂起该进程;

ctrl + d: ( Terminate input, or exit shell ) 一个特殊的二进制值,表示 EOF,作用相当于在终端中输入exit后回车;

ctrl + /   发送 SIGQUIT 信号给前台进程组中的所有进程,终止前台进程并生成 core 文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值