首页 > 技术文章 > 信息安全系统设计基础第十周学习总结

20135302wei 2015-11-15 18:21 原文

第十章 系统级I/O

 

第七节 I/O重定向

 

I/O重定向操作符: >

 

ls > foo.txt

 

这句代码的含义就是使外壳加载和执行ls程序,并且将标准输出重定向到磁盘文件foo.txt

 

I/O重定向函数: dup2

 

返回值:成功返回描述符,错误返回-1

 

这个函数执行的操作是,拷贝描述符表表项oldfd,覆盖描述表表项newfd,如果后者被打开,则在拷贝前关闭它。

 

第八节 标准I/O

 

1.标准I/O库:

 

ANSI C定义了一组高级输入输出函数,称为标准I/O库,包含:

 

  • fopenfclose,打开和关闭文件
  • freadfwrite,读和写字节
  • fgetsfputs,读和写字符串
  • scanfprintf,复杂的格式化的I/O函数

 

2.——类型为FILE的流是对文件描述符和流缓冲区的抽象

 

标准I/O库将一个打开的文件模型化为一个流。

 

每个ANSI C程序开始的时候都有三个打开的流:stdinstdoutstderr,对应于标准输入、标准输出和标准错误 

 

第九节 套接字

 

网络套接字上最好不要使用标准I/O函数,而是使用RIO函数,原因:

 

如果没有清楚缓存区,输入函数后面不能接输出函数,输出函数后面也不能接输入函数,而对套接字使用lseek是非法的,打开两个流有很麻烦,所以!在网络套接字上不要使用标准I/O函数来进行输入和输出!

 

错误处理

 

附录A中主要讲了这本书中的错误处理方式,有一个方法——错误处理包装函数,这个思想很有意思,相当于给基本函数再套上一层皮,然后run这个皮,发现了错误就终止,完全正确的话就跟没有这层皮一样。

 

1.错误处理风格

 

1Unix风格

 

遇到错误后返回-1,并且将全局变量errno设置为指明错误原因的错误代码;

 

如果成功完成,就返回有用的结果。

 

2Posix风格

 

返回0表示成功,返回非0表示失败;

 

有用的结果在传进来的函数参数中。

 

3DNS风格

 

有两个函数,gethostbynamegethostbyaddr,失败时返回NULL指针,并设置全局变量h_errno

 

2.错误处理包装函数

 

Unix风格

 

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

 

Posix风格

 

成功时返回void,错误返回码中不会包含有用的结果。

 

DNS风格

 

参考资料

 

1.《深入理解计算机系统》

 

 

 

 

 

实践代码

 

stdio.h 标准输入输出

 

stdlib.h C标准函数库

 

unistd.h Unix类系统定义符号常量

 

fcntl.h  定义了很多宏和open,fcntl函数原型

 

sys/types.h 基本系统数据类型

 

dirent.h unix类目录操作的头文件,包含了许多UNIX系统服务的函数原型,例如opendir函数、readdir函数。

 

termios.h 在Posix规范中定义的标准接口

 

cp

 

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]);

 

cp的参数有两个,分别是要复制的文件,和目的目录,检查cp的第一个参数,即要复制的文件,用open打开,in_fd为open返回的描述符,如果返回-1,代表打开失败,提示错误。检查cp的第二个参数,复制的目的地址,用create在目的地址创建新文件,out_fd为open返回的描述符,如果返回-1,代表创建失败,提示错误。cp指令的动作就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。

 

 

 

ls1

 

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);

 

}

 

}

 

Ls函数打开一个文件夹*dir,然后将其中的其中包含的文件名输出。不输入文件夹名字时默认为当前文件夹。

 

who

 

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

 

echostate 、setecho

 

 

 

这个代码是用来检查命令行中的提示符是否显示的,如果显示,输入的命令都可见,不显示则表示输入的命令不可见,结合setecho代码一起。

 

 

 

                info.c_lflag |= ECHO ;/*打开提示符*/

 

                info.c_lflag &= ~ECHO ;/*隐藏提示符*/

 

 

 

fileinfo

 

这个功能用来实现显示文件信息,建立了一个stat数据结构。

 

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

 

用st_size成员来计算文件的字节数大小。

 

spwd

 

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);

 

}

 

列出当前所在目录

 

testioctl

 

列出文件的行数与列数。

 

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

 

return 0;

 

 

 

编译完成后的文件列表:

 

a

 

a.out

 

cp1.c

 

cp1

 

echostate.c

 

error

 

fileinfo.c

 

fileinfo

 

filesize.c

 

filesize

 

foo.txt

 

ls1

 

ls1.c

 

ls2

 

ls2.c

 

setecho.c

 

spwd

 

spwd.c

 

test

 

testioctl.c

 

who1.c

 

who1

 

who2.c

 

who2

 

推荐阅读