2017-2018-1 20155205 《信息安全系统设计基础》第四周学习总结
2017-2018-1 20155205 《信息安全系统设计基础》第四周学习总结
课上实践--myod-系统调用版本
-
要求:
1.参考教材第十章内容 2.用Linux IO相关系统调用编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能,注意XXX是文件名,通过命令行传入,不要让用户输入文件名 3.不要把代码都写入main函数中 4.要分模块,不要把代码都写入一个.c中 5.提交测试代码和运行结果截图,提交调试过程截图,要全屏,包含自己的学号信息 6.课上上传代码到码云
head,tail的相关学习
相关API的分析
- head
- 语法:head [参数] 文件
- 命令功能:head用来显示档案的开头至标准输出当中,默认head命令打印其相应文件的开头10行。
-c<字符数>:指定显示头部内容的字符数
-n<数字>:指定显示头部内容的行数
来自: http://man.linuxde.net/head
- tail
- 功能:显示指定文件的后若干行。
- 语法: tail [+ / - num ] [参数] 文件
- tail命令中各个选项的含义为:+num 从第num行以后开始显示。-num 从距文件尾 num行处开始显示。如果省略 num参数,系统默认值为 10。
- 使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新,使你看到最新的文件内容。
伪代码,产品代码,测试代码的编写
- myhead
伪代码:
打开文件;
循环按字符读入文件,每读一个换行符计数器加一;
读满10个换行符停止输出;
结束程序
产品代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int fd,c=0;
char ch;
fd=open(argv[1],O_RDONLY,0);
if(fd==-1)
{
printf("出现错误!");
exit(1);
}
while(read(fd,&ch,1)!=0)
{
printf("%c",ch);
if(ch=='\n') c++;
if(c==10) break;
}//方法参考p599图10-2程序,将while循环中的write(fd,&ch,1)改为从屏幕输出字符,并加入了判断。
close(fd);
exit(0);
}
- tail
伪代码:
打开文件;
循环按字符第一次读入文件,统计总共的行数;
再次读入文件,当行数>=总行数-10时输出字符;
结束程序
产品代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int fd1,fd2,c=0,n=0;
char ch;
fd1=open(argv[1],O_RDONLY,0);
if(fd1==-1)
{
printf("出现错误!");
exit(1);
}
while(read(fd1,&ch,1)!=0)
{
if(ch=='\n') c++;
}
close(fd1);
fd2=open(argv[1],O_RDONLY,0);
while(read(fd2,&ch,1)!=0)
{
if(ch=='\n') n++;
if(n>=c-10)printf("%c",ch);
}
close(fd2);
exit(0);
}
教材学习中的问题和解决过程
-
问题1:练习题10.1程序的输出为什么是3?即打开文件和文件描述符的关系是什么?
-
问题1解决方案:
查阅资料后有段话解释了我的问题:
在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3,再调用open 就会返回4。
而且我了解到
每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的 信息,称为进程描述符(Process Descriptor),而在操作系统理论中称为进程控制块 (PCB,Process Control Block)。task_struct中有一个指针(struct files_struct *files; )指向files_struct结构体,称为文件 描述符表,其中每个表项包含一个指向已打开的文件的指针,如下图所示。
用户程序不能直接访问内核中的文件描述符表,而只能使用文件描述符表的索引 (即0、1、2、3这些数字),这些索引就称为文件描述符(File Descriptor),用int 型变量保存。 当调用open 打开一个文件或创建一个新文件时,内核分配一个文件描述符并返回给用户程序,该文件描述符表项中的指针指向新打开的文件。当读写文件时,用户程序把文件描述符传给read 或write ,内核根据文件描述符找到相应的表项,再通过表项中的指针找到相应的文件。
这就加深了我对打开文件和文件描述符的理解,也知道了家庭作业10.6的答案:因为调用了两次open函数,所以返回值是4,然后调用close释放了描述符4,再次调用open返回值又是4了,所以输出是4。
自己敲代码验证了一下:
代码学习中的问题和解决过程
- 问题1:运行程序时遇到了头文件csapp.h错误的情况
- 问题1解决方案:csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载。《深入理解计算机系统》配套网站
下载并解压后(以 root 身份登录)应该是一个code的文件夹,在其子文件夹include和src中分别可以找到csapp.h和csapp.c两个文件,把这两个文件拷贝到文件夹/usr/include里面,并在csapp.h文件中 #endif 之前加上一句 #include<csapp.h> ,然后编译时在最后加上 “-lpthread” 例如:gcc main.c -lpthread 就可以编译了。