2017-2018-1 20155228 《信息安全系统设计基础》第四周学习总结
myod-系统调用版本
题目和要求
- 参考教材第十章内容
- 用Linux IO相关系统调用编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能,注意XXX是文件名,通过命令行传入,不要让用户输入文件名
- 不要把代码都写入main函数中
- 要分模块,不要把代码都写入一个.c中
- 提交测试代码和运行结果截图, 提交调试过程截图,要全屏,包含自己的学号信息
- 课上上传代码到码云
分析和设计
关于linux中的od命令的分析
od -tx -tc /*选项和参数*/ hello.c /*当前目录下的文件的名字*/
选项 | 参数 | 解释 |
---|---|---|
- A | o | 指定地址基数为八进制(系统默认) |
- A | d | 指定地址基数为十进制 |
- A | x | 指定地址基数为十六进制 |
- A | n | 不打印位移值 |
- t | c | 指定数据的显示格式为ASCII字符或反斜杠序列 |
- t | o | 指定数据的显示格式为八进制(系统默认) |
- t | d | 指定数据的显示格式为有符号十进制数 |
- t | u | 指定数据的显示格式为无符号十进制数 |
- t | f | 指定数据的显示格式为浮点数 |
- t | x | 指定数据的显示格式为十六进制数 |
在选项-t中除了参数c,其他参数都可在后面加上一个十进制数n,用来指定连续显示的字节数量
- 详细介绍:详细介绍Linux指令od
关于系统调用的指令
- myod中需要用到的系统调用指令有三个
- 打开文件函数
使用这个函数时需要添加的头文件:int open(char *filename,int flags,mode_t mode); //int是文件描述符,文件打开失败时为-1,char *filename是文件路径,int flags是文件访问方式,包括只读只写读写,mode_t mode是文件访问权限
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
- 读取文件字符函数
使用这个函数时需要添加的头文件:ssize_t read(int fd,const void *buf,size_t n); //ssize_t是读的字节数,读不到字符(EOF)的时候为0,出错时为-1,int fd是文件描述符,const void *buf是把读到的字符放到指针buf所指的内存空间
#include <unistd.h>
- 关闭文件函数
使用这个函数时需要添加的头文件:int close(int fd); //int在关闭文件成时为0,关闭文件失败时为-1,int fd是文件描述符
#include <unistd.h>
代码和结果
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int m,n;
openfile(char *filename);
closefile();
void main(int argc,char *argv[])
{
char temp;
char ch[8];
int count1=0;
int count2=0;
openfile(argv[1]);
while(read(m,&temp,1)!=0)
{
if(count1<7)
{
if(count1==0)
printf(" ");
printf("%4x ",temp);
ch[count1]=temp;
count1++;
count2++;
}
else
{
printf("%4x ",temp);
ch[count1]=temp;
count1++;
count2++;
printf("\n");
printf("%4d ",count2);
for(int i=0;i<8;i++)
{
if(ch[i]=='\n')
{
printf(" \\n ");
}
else
{
printf("%4c ",ch[i]);
}
}
printf("\n");
count1=0;
}
}
if(count1!=0)
{
printf("\n%4d ",count2);
for(int i=0;i<count1;i++)
{
if(ch[i]=='\n')
{
printf(" \\n ");
}
else
{
printf("%4c ",ch[i]);
}
}
printf("\n");
}
closefile();
}
openfile(char *filename)
{
m=open(filename,O_RDONLY,0);
if(m==-1)
{
printf("file open faild!\n");
}
/*else
{
printf("file open successful!\n");
}*/
}
closefile()
{
n=close(m);
if(n==-1)
{
printf("file close faild!\n");
}
/*else
{
printf("file close successful!\n");
}*/
}
问题和解决
关于输出打印排版的问题
- 问题:在
od -tx1 -tc hello.c
中,每行打印16个字符,每行开头还有统计总的字符个数 - 解决:在
myod
中,用conut1来控制每行打印8个字符,用count2统计总的字符个数 - 问题:在
od -tx1 -tc hello.c
中,打印格式是一行ascii码和一行字符相互对应 - 解决:在
myod
中,用conut1来控制每行打印8个字符,每打印一个字符的ascii码就用ch数组记录这个字符,当打印8个字符的ascii码之后,就换行打印ch数组中的8个字符
关于直接在命令中传参的问题
void main(int argc,char *argv[])
- 如果想要直接在命令行中传参而不是运行程序再输参数,主函数就必须套用上面这种格式
- int argc是输入参数的个数
- char *argv是各个输入的参数,一个参数一个字符串
- 嗨呀好气呀我之前不知道必须要写成这种格式我还以为可以自己设定mian函数的输入格式搞了半天总是文件打开失败我都想砸电脑了
- 我后来去翻大佬们的博客发现大家都写成这个格式我最初还以为大家都是抄同一个人的代码所以参数都一样结果上网查了才知道必须这样写
- 详细分析:int main(int argc,char* argv[])详解
教材学习内容总结
第十章 系统级I/O
Linux提供了少量的基于Unix I/O模型的系统级函数.它们允许应用程序打开、关闭、读和写文件,提取文件的元数据,以及执行I/ O重定向。Linux的读和写操作会出现不足值,应用程序必须能正确地预计和处理这种情况。应用程序不应直接调用Unix I/O函数,而应该使用RIO包,RIO包通过反复执行读写操作,直到传送完所有的请求数据,自动处理不足值。Linux内核使用三个相关的数据结构来表示打开的文件。描述符表中的表项指向打开文件表中的表项,而打开文件表中的表项又指向v-node表中的表项。每个进程都有它自己单独的描述符表,而所有的进程共享同一个打开文件表和v-node表。理解这些结构的一般组成就能使我们清楚地理解文件共享和I/O重定向。标准I/()库是基于Unix I/O实现的,并提供了一组强大的高级I/O例程。对于大多数应用程序而言,标准I/ O更简单,是优于Unix I/O的选择。然而,因为对标准I/O和网络文件的一些相互不兼容的限制,Unix I/O比之标准I/O更该适用于网络应用程序。
附录A 错误处理
#include "csapp.h"
void unix_error(char *msg)
void posix_error(int code,char *msg);
void gai_error(int code,char *msg);
void app_error(char *msg);
unix_error, posix_error和gai_error函数报告Unix风格的错误、Posix风格的错误和GAI风格的错误,然后终止。包括app_error函数是为了方便报告应用错误。它只是简单地打印它的输人,然后终止。
完成head,tail的使用,相关API的分析,伪代码,产品代码,测试代码的编写
分析和设计
对head
和tail
命令的分析
- head命令用来查看文件的前几行内容,默认是查看前10行的内容,也可以设置一个数字改变查看行数
head hello.c/*当前目录下的文件名称*/
head -20 hello.c
- tail命令用来查看文件的最后几行内容,默认是查看最后10行的内容,同样,也可以设置一个数字改变查看行数
tail -20 hello.c
代码和结果
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int m,n;
void fileopen(char *filename);
void fileclose();
void main(int argc,char *argv[])
{
char temp;
int count1,count2;
count2=0;
count1=atoi(argv[1]);
fileopen(argv[2]);
while(read(m,&temp,1)!=0)
{
if(temp=='\n')
{
count2++;
if(count2==count1)
{
goto A;
}
else
{
printf("%c",temp);
}
}
else
{
printf("%c",temp);
}
}
A:
printf("\n");
fileclose;
}
void fileopen(char *filename)
{
m=open(filename,O_RDONLY,0);
if(m==-1)
{
printf("file open faild!\n");
}
}
void fileclose()
{
n=close(m);
if(n==-1)
{
printf("file close faild!\n");
}
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int m,n;
void fileopen(char *filename);
void fileclose();
void main(int argc,char *argv[])
{
char temp;
int count1,count2;
count2=0;
count1=atoi(argv[1]);
fileopen(argv[2]);
while(read(m,&temp,1)!=0)
{
if(temp=='\n')
{
count2++;
}
}
//printf("count2=%d\n",count2);
count2=count2-count1;
count1=0;
fileclose;
fileopen(argv[2]);
while(read(m,&temp,1)!=0)
{
if(temp=='\n')
{
count1++;
}
//printf("count1=%d\n",count1);
if(count1>=count2)
{
printf("%c",temp);
}
}
printf("\n");
fileclose;
}
void fileopen(char *filename)
{
m=open(filename,O_RDONLY,0);
if(m==-1)
{
printf("file open faild!\n");
}
}
void fileclose()
{
n=close(m);
if(n==-1)
{
printf("file close faild!\n");
}
}
问题和解决
关于在命令行传参时将字符串转为数字
- 问题:
head
和tail
有两个参数,一个是数字(行数)一个是字符串(地址),但是main(int argc,char *argv[])
传参都是字符串 - 解决:使用
#include <stdlib.h>
中的count1=atoi(argv[1]);
函数把字符串转成数字 - 详细分析:C语言字符串与数字相互转换
代码托管
在Ubuntu上安装CodeBlocks
本周结对学习情况
- [201552222](http://www.cnblogs.com/20155222lzj/))
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 10/10 | 1/1 | 6/12 | |
第三周 | 220/230 | 2/3 | 6/18 | |
第四周 | 270/500 | 1/4 | 6/24 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:6小时
实际学习时间:6小时
(有空多看看现代软件工程 课件 软件工程师能力自我评价表)