2017-2018-1 20155218 《信息安全系统设计基础》第四周学习总结
1.myod-系统调用版本
(1). 题目要求:
1.参考教材第十章内容
2 用LinuxIO相关系统调用编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能,注意XXX是文件名,通过命令行传入,不要让用户输入文件名
3.不要把代码都写入main函数中
4.要分模块,不要把代码都写入一个.c中
5.提交测试代码和运行结果截图, 提交调试过程截图,要全屏,包含自己的学号信息
(2)实现过程
1. od 命令能干什么
通过
man od
来查看
用户通常使用od命令查看特殊格式的文件内容。通过指定该命令的不同选项可以以十进制、八进制、十六进制和ASCII码来显示文件。
2.如何实现myod-系统调用版本
对比两次myod的实习,这次的myod需要使用系统调用,即open和read。
open
函数open是UNIX系统的系统调用函数,区别于C语言库函数fopen。包含在头文件
#include <fcntl.h>
,作用:打开和创建文件。
int open(constchar*pathname, int flags);
int open(constchar*pathname, int flags, mode_t mode);
返回值:成功则返回文件描述符,否则返回-1
参数说明:对于open函数来说,第三个参数仅当创建新文件时(即使用了O_CREAT 时)才使用,用于指定文件的访问权限位(access permission bits)。pathname是待打开/创建文件的POSIX路径名(如/home/user/a.cpp);flags用于指定文件的打开/创建模式,这个参数可由以下常量(定义于fcntl.h)通过逻辑位或逻辑构成。
O_RDONLY 只读模式
O_WRONLY 只写模式
O_RDWR 读写模式
read
通过 man 2 read 来了解相关知识。
返回值:
RETURN VALUES
If successful, the number of bytes actually read is returned. Upon read-
ing end-of-file, zero is returned. Otherwise, a -1 is returned and the
global variable errno is set to indicate the error.
返回值-1表示一个错误,而返回值0表示EOF。否则,返回值表示的是实际传送的字节数量。
实现myod
通过对上个版本的myod进行修改。
fd=open(argv[1], O_RDONLY,0);
通过调用open函数来打开文件。
read(fd,&ch,1)!=0
通过read函数来读取文件。
主函数:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
// insert code here...
int fd;
fd=open(argv[1], O_RDONLY,0);
myod(fd);
close(fd);
}
myod:
void myod(int fd)
{
char c,line[16];
int i;
int k=0;
int j=0;
while(read(fd,&c,1)!=0){
line[j%16]=c;
if((j+1)%16==0){
printf("%07o ",16*k);
k++;
for(j=0;j<16;j++)
{
printf("%3c",line[j]);
putchar(' ');
}
printf("
");
printf(" ");
putchar(' ');
for(int m=0;m<16;m++)
{
printf("%3x",line[m]);
putchar(' ');
}
printf("
");
putchar('
');}
j++;
}
}
结果截图:
完成head,tail
RIO 一个用缓冲区实现的IO系统
3.1 RIO中rio_read函数的编写思想:
a)采用预读取方案,提前把数据读入Buffer;
b)每当用户取数据的时候,从Buffer里面读取,而不是使用系统调用read函数,这样减少了多次使用系统调用的开销。
3.2 rio_read函数的编写原则:必须与系统的 read 函数保持语义一致,这意味着rio_read的返回值有三种情况:
a) -1代表出错,这里不包含EINTR;
b) 0代表EOF,读取结束;
c) >0表示读取的字节数。
首先查看head和tail的功能;
实际使用:
设计思路:同样通过open和read来读取文件,只需要控制读取的行数(10行),即可实现所需的功能;
HEAD:
主函数:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int fd=0;
fd=open(argv[1],O_RDONLY);
mh(fd);
close(fd);
return 0;
}
mh函数:
void mh(int fd){
int count=0;
char c;
while(read(fd,&c,1)!=0)
{
putchar(c);
if(c == '
')
count++;
if(count == 10)
break;
}
}
结果截图:
TAIL
产品代码:
设计思路:先统计文件有多少行,然后输出后十行
1#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 int ct(int fd){
8 int count=0;
9 char c;
10 while(read(fd,&c,1)!=0)
11 {
12 if(c == '
')
13 count++;
14
15 }
16 return count;
17 }
18 void mh(int fd,int n)
19 {
20 int count=0;
21 char c;
22 while (read(fd, &c, 1)!=0) {
23 if (c=='
')
24 {
25 count++;
26 }
27 if (count>=n-10) {
28 putchar(c);
29
30 }
31
32 }
33
34 }
35 int main(int argc,char *argv[])
36 {
37
38
39 int fd=0,ft=0;
40 int count;
41 fd=open(argv[1],O_RDONLY);
42 count=ct(fd);
43 close(fd);
44 ft=open(argv[1],O_RDONLY);
45 mh(fd,count);
46 close(ft);
47 return 0;
48 }
截图:
因为重复使用了hello.txt文件,第一次就把指针移动到了文件尾,所以第二次就没有任何输出。后来查找资料,找到了问题,也找到了解决的方法:使用fseek函数进行跳转。比如“起始点”参数设置为SEEK_SET 即可将文件指针挪到文件开头位置再次读取,反复这样操作,即可实现重复读取文件。
fseek(fp,100L,SEEK_SET); //将文件位置标记向前移到离文件开头100