第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 文件