信息安全系统设计基础第十周学习总结

信息安全系统设计基础第十周学习总结

估算学习时间:共9小时
读书:4
代码:3
作业:0
博客:2
实际学习时间:共7.5小时
读书:2.5
代码:3.5
作业:0
博客:1.5
耗时估计的公式:Y=X+X/N ,Y=X-X/N

课本第十章 系统级I/O

  • 输入输出I/O是在主存和外部设备(如磁盘,网络和终端)之间拷贝数据的过程。
  • 输入就是从I/O设备拷贝数据到主存,而输出就是从主存拷贝数据到I/O设备。
  • 所有语言的运行时系统都提供执行I/O的较高级别的工具。例如,ANSI C提供标准I/O库,包含像printf和scanf这样执行带缓冲区的I/O函数。C++语言用它的重载操作符<<(输出)和>>(输入)提供了类似的功能。在UNIX系统中,是通过使用由内核提供的系统级Unix I/O函数来实现这些比较高级的I/O函数的。
  • 学习Unix I/O原因:了解Unix I/O将帮助你理解其他的系统概念;有时你除了使用Unix I/O外别无选择。

10.1 unix i/o 596

所有的I/O设备,如网络、磁盘和终端,都被模型化为文件,而所有的输入和输出都被当做对相应的文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Unix内核引出一个简单、低级的的应用接口,称为Unⅸ I/O,这使得所有的输入和输出都能以一种统一且一致的方式来执行:

  • 打开文件。一个应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备。内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有操作中标识这个文件。内核记录有关这个打开文件的所有信息。应用程序只需记住这个描述符。Unⅸ外壳创建的每个进程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)和标准错误(描述符为2)。头文件可用来代替显式的描述符值。
  • 改变当前的文件位置。对于每个打开的文件,内核保持着一个文件位置k,初始为0。这个文件位置是从文件开头起始的字节偏移量。应用程序能够通过执行seek操作,显式地设置文件的当前位置为k。
  • 读写文件。一个读操作就是从文件拷贝n>0个字节到存储器,从当前文件位置k开始,然后将k增加到k+n。给定一个大小为m字节的文件,当k>=m时执行读操作会触发―个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。在文件结尾处处并没有明确的“EOF”符号。
  • 关闭文件。当应用完成了对文件的访问之后,它就通知内核关闭这个文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。无论一个进程因为何种原因终止时,内核都会关闭所有打开的文件并释放它们的存储器资源。

10.2 打开和关闭文件 597

  • 进程是通过调用open函数来打开一个已存在的文件或者创建一个新文件:

  • flags参数表示进程打算如何访问这个文件,它的值包括:

O_RDONLY
O_WRONLY
O_RDWR

  • flags参数也可以是一个或者更多位掩码的或,提供一些额外的指示:

O_CREAT
O_TRUNC:如果文件已经存在,就截断它。
O_APPEND

  • mode参数指定了新文件的访问权限位。符号名字如下图。作为上下文的一部分,每个进程都有一个umask它是通过调用umask函数来设置的。当进程通过带某个mode参数的open函数调用来创建一个新文件时,文件的访问权限位被设置为mode&umask。

10.3 读和写文件 598

应用程序是通过分别调用系统函数 read和write函数来执行输入和输出的。

旁注:size_t是作为usigned int,而ssize_t是作为int。

在某些情况下,read和write传送的字节比应用程序要求的要少。出现这种情况的可能的原因有:

读时遇到EOF。假设该文件从当前文件位置开始只含有20个字节,而应用程序要求我们以50个字节的片进行读取,这样一来,这个read的返回的值是20,在此之后的read则返回0。
从终端读文本行。如果打开的文件是与终端相关联的,那么每个read函数将一次传送一个文本行,返回的不足值等于文本行的大小。
读和写socket。如果打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会导致read和write返回不足值。

10.4 用rio包健壮地读写 599

RIO提供了两类不同的函数:

无缓冲的输入输出函数
带缓冲的输入函数

10.4.1 rio的无缓冲的输入输出函数 600

  • rio_readn函数从描述符fd的当前文件位置最多传送n个字节到存储器位置usrbuf。类似的rio_writen函数从位置usrbuf传送n个字节到描述符fd。rio_readn函数在遇到EOF时只能返回一个不足值。rio_writen函数绝不会返回不足值。
  • 注意:如果rio_readn和rio_writen函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动地重启read或write。

10.4.2 rio的带缓冲的输入函数 600

  • 一个文本行就是一个由 换行符 结尾的ASCII码字符序列。在Unix系统中,换行符是‘\n’,与ASCII码换行符LF相同,数值为0x0a。假设我们要编写一个程序来计算文本文件中文本行的数量应该如何来实现呢?

一种方法是用read函数来一次一个字节地从文件传送到用户存储器,检查每个字节来查找换行符。这种方法的问题就是效率不高,每次取文件中的一个字节都要求陷入内核。
一种更好的方法是调用一个包装函数(rio_readlineb),它从一个内部缓冲区拷贝一个文本行,当缓冲区变空时,会自动的调用read系统调用来重新填满缓冲区。

  • 在带缓冲区的版本中,每打开一个描述符都会调用一次rio_readinitb函数,它将描述符fd和地址rp处的一个类型为rio_t的读缓冲区联系起来。
  • rio_readinitb函数从文件rp读取一个文本行(包括结尾的换行符),将它拷贝到存储器位置usrbuf,并且用空字符来结束这个文本行。
  • RIO读程序的核心是rio_read函数,rio_read函数可以看成是Unix read函数的带缓冲区的版本。当调用rio_read要求读取n个字节的时候,读缓冲区内有rp->rio_cnt个未读的字节。如果缓冲区为空的时候,就会调用read系统函数去填满缓冲区。这个read调用收到一个不足值的话并不是一个错误,只不过读缓冲区的是填充了一部分。
  • 一旦缓冲区非空,rio_read就从读缓冲区拷贝n和rp->rio_cnt中较小值个字节到用户缓冲区,并返回拷贝字节的数目。
  • 对于应用程序来说,rio_read和系统调用read有着相同的语义。出错时返回-1;在EOF时,返回0;如果要求的字节超过了读缓冲区内未读的字节的数目,它会返回一个不足值。rio_readlineb函数多次调用rio_read函数。每次调用都从读缓冲区返回一个字节,然后检查这个字节是否是结尾的换行符。
  • rio_readlineb函数最多读取(maxlen-1)个字节,余下的一个字节留给结尾的空字符。超过maxlen-1字节的文本行被截断,并用一个空字符结束。

10.5 读取文件元数据 604

  • 应用程序能够通过调用stat和fstat函数,检索到关于文件的信息。

  • stat函数结构

  • st_size成员包含了文件的字节数大小。st_mode成员则编码了文件访问许可位和文件类型。Unix识别大量不同的文件类型。普通文件包括某种类型的二进制或文本数据。对于内核而言,文本文件和二进制文件毫无区别。

  • 目录文件包含关于其他文件的信息。套接字是一种用来通过网络与其他进程通信的文件。Unix提供的宏指令根据st_mode成员来确定文件的类型。这些宏的一个子集如下:

10.6 共享文件 606

内核用三个相关数据结构来表示打开的文件

描述符表
文件表
v-node表

10.7 i/o重定向 608

  • Unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出联系起来。

  • I/O重定向的工作方式: 一种是使用dup2函数。

  • dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。

10.8 标准i/o 609

  • ANSI C定义了一组高级输入输出函数,成为标准I/O库,为程序员提供了Unix I/O的较高级别的替代。这个库(libc)提供了打开和关闭文件的函数(fopen和fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs)、以及复杂的格式化I/O函数(printf和scanf)。

  • 标准I/O库将一个打开的文件模型化为一个流。对于程序员而言,一个流就是一个指向FILE类型的结构的指针。每个ANSI C程序开始时都有三个打开的流stdin、stdout和stderr,分别对应于标准输入、标准输出和标准错误:

10.9 综合:我该使用哪些i/o函数 610

  • 这一章讨论过的各种I/O包

  • 标准I/O流,从某种意义上来说是全双工的,因为程序能够在同一个流上执行输入和输出。

  • 建议在网络套接字上不要使用标准I/O函数来进行输入和输出。而要使用健壮的RIO函数。

10.10 小结 611

  • Unix提供了少量的系统级函数,它们允许应用程序打开、关闭、读和写文件,提取文件的元数据,以及执行I/O重定向。Unix的读和写操作会出现不足值,应用程序必须能正确地预计和处理这种情况。应用程序不应直接调用unⅸ I/O函数,而应该使用RIO包,RIO包通过反复执行读写操作,直到传送完所有的请求数据,自动处理不足值。
  • Unix内核使用三个相关的数据结构来表示打开的文件。描述符表中的表项指向打开文件中的表项,而打开文件表中的表项又指向v-node表中的表项,每个进程都有它自己单独的描述符表,而所有的进程共享同一个打开文件表和v-node表,理解这些结构的一般组成就能使我们清楚地理解文件共享和I/O重定向。
  • 标准I/O库是基于Unix I/O实现的,并提供了一组强大的高级I/O例程,对于大多数应用程序而言,标准I/O更简单,是优于Unix I/O的选择。然而,因为对标准I/O和网络文件的一些相互不兼容的限制,Unix I/O比标准I/O更适用于网络应用程序。

附录A错误处理

A.1 Unix系统中的错误处理

  1. Unix风格的处理错误
    遇到错误后返回-1,并且将全局变量errno设置为指明错误原因的错误代码;
    如果成功完成,就返回有用的结果。

  2. Posix风格的处理错误
    返回0表示成功,返回非0表示失败;
    有用的结果在传进来的函数参数中。

  3. DNS风格的处理错误
    有两个函数,gethostbyname和gethostbyaddr,失败时返回NULL指针,并设置全局变量h_errno。

  4. 错误报告函数小结
    贯穿本书,使用下列错误报告函数来包容不同的错误处理风格:

    ``#include "csapp.h"
    void unix_error(char *msg);
    void posix_error(int code,char *msg);
    void dns_error(char *msg);
    void app_error(char *msg);

A.2 错误处理包装函数

  • Unix风格
    成功时返回void,返回错误时包装函数打印一条信息,然后退出。

      void Kill(pid_t pid, int signum) 
      {
      int rc;
      if ((rc = kill(pid, signum)) < 0)
      	unix_error("Kill error");
      }
    
  • Posix风格
    成功时返回void,错误返回码中不会包含有用的结果。

      void Pthread_detach(pthread_t tid) {
      int rc;
    
      if ((rc = pthread_detach(tid)) != 0)
      	posix_error(rc, "Pthread_detach error");
      }
    
  • DNS风格

      struct hostent *Gethostbyname(const char *name) 
      {
      	struct hostent *p;
    
      	if ((p = gethostbyname(name)) == NULL)
      	dns_error("Gethostbyname error");
      	return p;
       }
    

编译运行代码

cp1.c
echostate.c
fileinfo.c
filesize.c
ls1.c
ls2.c
setecho.c
spwd.c
testioctl.c
who1.c
who2.c

cp1

复制文件。

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

define BUFFERSIZE      4096
#define COPYMODE        0644

void oops(char *, char *);

int main(int argc, char *argv[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
if (argc != 3) {
	fprintf(stderr, "usage: %s source destination\n", *argv);
	exit(1);
}

if ((in_fd = open(argv[1], O_RDONLY)) == -1)
	oops("Cannot open ", argv[1]);

if ((out_fd = creat(argv[2], COPYMODE)) == -1)
	oops("Cannot creat", argv[2]);

while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
	if (write(out_fd, buf, n_chars) != n_chars)
		oops("Write error to ", argv[2]);
if (n_chars == -1)
	oops("Read error from ", argv[1]);


if (close(in_fd) == -1 || close(out_fd) == -1)
	oops("Error closing files", "");
}

void oops(char *s1, char *s2)
{
fprintf(stderr, "Error: %s ", s1);
perror(s2);
exit(1);
}

运行结果如下:

echostate

检验在命令行中输入命令时是否可见,如果可见,返回echo is on , since its bit is 1

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

int main()
{
struct termios info;
int rv;

rv = tcgetattr( 0, &info ); /* read values from driver  */

if ( rv == -1 ){
perror( "tcgetattr");
exit(1);
}
if ( info.c_lflag & ECHO )
printf(" echo is on , since its bit is 1\n");
else
printf(" echo is OFF, since its bit is 0\n");

		return 0;
}

运行结果如下:

fileinfo

查看文件信息。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

void show_stat_info(char *, struct stat *);

int main(int argc, char *argv[])
{
struct stat info;

if (argc>1)
	{
	
if( stat(argv[1], &info) != -1 ){
show_stat_info( argv[1], &info );
return 0;
}
else
perror(argv[1]);  
	}
return 1;
}
void show_stat_info(char *fname, struct stat *buf)
{
printf("   mode: %o\n", buf->st_mode); 
printf("  links: %d\n", buf->st_nlink);
printf("   user: %d\n", buf->st_uid);  
printf("  group: %d\n", buf->st_gid);  
printf("   size: %d\n", (int)buf->st_size); 
printf("modtime: %d\n", (int)buf->st_mtime);
printf("   name: %s\n", fname );   
}

运行结果如下:

filesize

计算文件的字节数大小。

#include <stdio.h>
#include <sys/stat.h>

int main()
{
	struct stat infobuf;   

	if ( stat( "/etc/passwd", &infobuf) == -1 )
		perror("/etc/passwd");
	else
		printf(" The size of /etc/passwd is %d\n", infobuf.st_size );
}

ls1

显示当前目录下的文件。

#include	<stdio.h>
#include	<sys/types.h>
#include	<dirent.h>

void do_ls(char []);

int main(int argc, char *argv[])
{
	if ( argc == 1 )
		do_ls( "." );
	else
		while ( --argc ){
			printf("%s:\n", *++argv );
			do_ls( *argv );
		}

	return 0;
}

void do_ls( char dirname[] )
{
	DIR		*dir_ptr;		
	struct dirent	*direntp;		

	if ( ( dir_ptr = opendir( dirname ) ) == NULL )
		fprintf(stderr,"ls1: cannot open %s\n", dirname);
	else
	{
		while ( ( direntp = readdir( dir_ptr ) ) != NULL )
			printf("%s\n", direntp->d_name );
		closedir(dir_ptr);
	}
}

运行结果如下:

ls2

查看文件的详细信息,比如用户名,群组名,大小,创建时间,读写权限等。

#include	<stdio.h>
#include<string.h>
#include	<sys/types.h>
#include	<dirent.h>
#include	<sys/stat.h>

void do_ls(char[]);
void dostat(char *);
void show_file_info( char *, struct stat *);
void mode_to_letters( int , char [] );
char *uid_to_name( uid_t );
char *gid_to_name( gid_t );

int main(int argc, char *argv[])
{
	if ( argc == 1 )
		do_ls( "." );
	else
		while ( --argc ){
			printf("%s:\n", *++argv );
			do_ls( *argv );
		}

	return 0;
}

void do_ls( char dirname[] )
{
	DIR		*dir_ptr;		
	struct dirent	*direntp;		

	if ( ( dir_ptr = opendir( dirname ) ) == NULL )
		fprintf(stderr,"ls1: cannot open %s\n", dirname);
	else
	{
		while ( ( direntp = readdir( dir_ptr ) ) != NULL )
			dostat( direntp->d_name );
		closedir(dir_ptr);
	}
}

void dostat( char *filename )
{
	struct stat info;

	if ( stat(filename, &info) == -1 )		
		perror( filename );			
	else					
		show_file_info( filename, &info );
}

void show_file_info( char *filename, struct stat *info_p )
{
	char	*uid_to_name(), *ctime(), *gid_to_name(), *filemode();
	void	mode_to_letters();
charmodestr[11];

	mode_to_letters( info_p->st_mode, modestr );

	printf( "%s", modestr );
	printf( "%4d "  , (int) info_p->st_nlink);	
	printf( "%-8s " , uid_to_name(info_p->st_uid) );
	printf( "%-8s " , gid_to_name(info_p->st_gid) );
	printf( "%8ld " , (long)info_p->st_size);
	printf( "%.12s ", 4+ctime(&info_p->st_mtime));
	printf( "%s\n"  , filename );

}

void mode_to_letters( int mode, char str[] )
{
strcpy( str, "----------" );   

if ( S_ISDIR(mode) )  str[0] = 'd';
if ( S_ISCHR(mode) )  str[0] = 'c';
if ( S_ISBLK(mode) )  str[0] = 'b';

if ( mode & S_IRUSR ) str[1] = 'r';
if ( mode & S_IWUSR ) str[2] = 'w';
if ( mode & S_IXUSR ) str[3] = 'x';

if ( mode & S_IRGRP ) str[4] = 'r';
if ( mode & S_IWGRP ) str[5] = 'w';
if ( mode & S_IXGRP ) str[6] = 'x';

if ( mode & S_IROTH ) str[7] = 'r';
if ( mode & S_IWOTH ) str[8] = 'w';
if ( mode & S_IXOTH ) str[9] = 'x';
}

#include	<pwd.h>

char *uid_to_name( uid_t uid )
{
	struct	passwd *getpwuid(), *pw_ptr;
	static  char numstr[10];

	if ( ( pw_ptr = getpwuid( uid ) ) == NULL ){
		sprintf(numstr,"%d", uid);
		return numstr;
	}
	else
		return pw_ptr->pw_name ;
}

#include	<grp.h>

char *gid_to_name( gid_t gid )
{
	struct group *getgrgid(), *grp_ptr;
	static  char numstr[10];

	if ( ( grp_ptr = getgrgid(gid) ) == NULL ){
		sprintf(numstr,"%d", gid);
		return numstr;
	}
	else
		return grp_ptr->gr_name;
}

运行结果如下:

setecho

设置在命令行中输入命令时是否可见,如果可见,输入setecho yes;如果设置为不可见,输入setecho no。

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

#define  oops(s,x) { perror(s); exit(x); }

int main(int argc, char *argv[])
{
struct termios info;

if ( argc == 1 ) 
		exit(0);

if ( tcgetattr(0,&info) == -1 )  /* get attribs   */
			oops("tcgettattr", 1);

if ( argv[1][0] == 'y' )
info.c_lflag |= ECHO ;  /* turn on bit*/
else
info.c_lflag &= ~ECHO ; /* turn off bit   */

if ( tcsetattr(0,TCSANOW,&info) == -1 ) /* set attribs*/
   oops("tcsetattr",2);
	
		return 0;
}

运行结果如图:

spwd

显示当前所在目录。

#include	<stdio.h>
#include<stdlib.h>
#include<string.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<dirent.h>

ino_t	get_inode(char *);
voidprintpathto(ino_t);
voidinum_to_name(ino_t , char *, int );

int main()
{
	printpathto( get_inode( "." ) );	
	putchar('\n');				
	return 0;
}

void printpathto( ino_t this_inode )
{
	ino_t	my_inode ;
	char	its_name[BUFSIZ];

	if ( get_inode("..") != this_inode )
	{
		chdir( ".." );				

		inum_to_name(this_inode,its_name,BUFSIZ);

		my_inode = get_inode( "." );		
		printpathto( my_inode );		
		printf("/%s", its_name );		
							
	}
}

void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen)
{
	DIR		*dir_ptr;		
	struct dirent	*direntp;		

	dir_ptr = opendir( "." );
	if ( dir_ptr == NULL ){
		perror( "." );
		exit(1);
	}


	while ( ( direntp = readdir( dir_ptr ) ) != NULL )
		if ( direntp->d_ino == inode_to_find )
		{
			strncpy( namebuf, direntp->d_name, buflen);
			namebuf[buflen-1] = '\0';   
			closedir( dir_ptr );
			return;
		}
	fprintf(stderr, "error looking for inum %d\n", (int) inode_to_find);
	exit(1);
}

ino_t get_inode( char *fname )
{
	struct stat info;

	if ( stat( fname , &info ) == -1 ){
		fprintf(stderr, "Cannot stat ");
		perror(fname);
		exit(1);
	}
	return info.st_ino;
}

运行结果如下:

testioctl

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main()
{
	struct winsize size;
	if( isatty(STDOUT_FILENO) == 0)
		exit(1);
	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0) {
		perror("ioctl TIOCGWINSZ error");
		exit(1);
	}

	printf("%d rows %d columns\n", size.ws_row, size.ws_col);
	return 0;
}

运行结果如下:

who1

从UTMP_FILE文件中读取想要的信息到存储器中,然后再用标准输出函数打印到屏幕上,最后关闭文件。

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

#define	SHOWHOST	

int show_info( struct utmp *utbufp )
{
	printf("%-8.8s", utbufp->ut_name);	
	printf(" ");				
	printf("%-8.8s", utbufp->ut_line);	
	printf(" ");				
	printf("%10ld", utbufp->ut_time);	
	printf(" ");				
#ifdef	SHOWHOST
	printf("(%s)", utbufp->ut_host);	
#endif
	printf("\n");				

	return 0;
}
int main()
{
	struct utmp	 current_record;	
	int		utmpfd;		
	int		reclen = sizeof(current_record);

	if ( (utmpfd = open(UTMP_FILE, O_RDONLY)) == -1 ){
		perror( UTMP_FILE );	
		exit(1);
	}
	while ( read(utmpfd, &current_record, reclen) == reclen )
		show_info(&current_record);
	close(utmpfd);
	return 0;			
}

运行结果如下:

who2

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

#define	SHOWHOST	

int show_info( struct utmp *utbufp )
{
	printf("%-8.8s", utbufp->ut_name);	
	printf(" ");				
	printf("%-8.8s", utbufp->ut_line);	
	printf(" ");				
	printf("%10ld", utbufp->ut_time);	
	printf(" ");				
#ifdef	SHOWHOST
	printf("(%s)", utbufp->ut_host);	
#endif
	printf("\n");				

	return 0;
}
int main()
{
	struct utmp	 current_record;	
	int		utmpfd;		
	int		reclen = sizeof(current_record);

	if ( (utmpfd = open(UTMP_FILE, O_RDONLY)) == -1 ){
		perror( UTMP_FILE );	
		exit(1);
	}
	while ( read(utmpfd, &current_record, reclen) == reclen )
		show_info(&current_record);
	close(utmpfd);
	return 0;			
}

运行结果如下:

用man学习理解相关系统调用, 理解参数、返回值的含义

1.Linux man中的man就是manual的缩写,用来查看系统中自带的各种参考手册,但是手册页分为好几个部分,如下所示:

1 Executable programs or shell commands(用户命令帮助)

# 2 System calls (系统调用帮助) #

3 Library calls (库函数调用帮助)

4 Special files (usually found in /dev)

5 File formats and conventions eg /etc/passwd(配置文件帮助)

6 Games

7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)

8 System administration commands (usually only for root)

9 Kernel routines [Non standard]

1是普通的命令  
2是系统调用,如open,write之类的(通过这个,至少可以很方便的查到调用这个函数,需要加什么头文件)  
3是库函数,如printf,fread4是特殊文件,也就是/dev下的各种设备文件  
5是指文件的格式,比如passwd, 就会说明这个文件中各个字段的含义  
6是给游戏留的,由各个游戏自己定义  
7是附件还有一些变量,比如向environ这种全局变量在这里就有说明  
8是系统管理用的命令,这些命令只能由root使用,如ifconfig  

2.man page大致分为一下部分:

NAME:简单命令、数据名称说明
SYNOPSIS:简短的命令语法(sysntax)简介
DESCRIPTION:较为完整的说明,需要认真阅读
OPTION:针对SYNOPSIS中列举的所有可用选项说明
COMMANDS:当这个软件在执行的时候,可用在此软件中使用命令
FILES:这个软件或数据所使用或参考或链接到的文件
SEE ALSE:可以参考的,与这个命令有关的其他说明
EXAMPLE:一些可以参考的范例,这个最好用
BUGS:是否有相关的bug

3.man中的相关操作

ctrl + F或者Page Down:向下翻页
ctrl + B或者Page Up:向上翻页
gg到第一行
GG到最后一行
/start:能在整手册中搜索start相关字符,使用n查找下一个,使用N查找上一个
j,k与vi中一样使用,j向下一行,k向上一行
d下翻半页
u上翻半页
h获取man使用帮助
q退出man

4.使用带有-k选项的man命令可以根据关键字搜索联机帮助。
使用带有-f选项的man命令可以根据关键字在联机帮助中搜索完全匹配的条目。
5.常见的系统调用命令见:http://www.2cto.com/os/201307/224623.html
6.利用man学习这些命令,例:

用grep -nr xxx /usr/include 查宏定义

感悟

如果想进一步了解系统,熟悉一些系统底层的东西还是非常必要的,可以先了解一些命令是如何实现相关功能的。

参考资料

  1. 教材:第十章,详细学习指导:http://group.cnblogs.com/topic/73069.html
  2. 课程资料:https://www.shiyanlou.com/courses/413 实验十,课程邀请码:W7FQKW4Y
  3. 教材中代码运行、思考一下,读代码的学习方法:http://www.cnblogs.com/rocedu/p/4837092.html。
  4. CSAPP第10章系统级I/O问题:http://www.zhihu.com/question/31499851
  5. Linux系统调用学习:http://blog.chinaunix.net/uid-20758579-id-1876888.html
posted @ 2015-11-15 16:33  xixixixixi  阅读(390)  评论(1编辑  收藏  举报