20145212 《信息安全系统设计基础》第12周学习总结
学习总结
课堂学习内容
指针数组与数组指针
1.指针数组:即用于存储指针的数组,也就是数组元素都是指针
举例说明:
int *a[3]
表示:数组a中的元素都为int型指针
元素表示:a[i] (a[i])也是一样的,因[]
优先级高于*
2.数组指针:即指向数组的指针,指针指向一个类型和元素个数都固定的数组
举例说明:
int (*a)[3]
表示:指向数组a的指针
元素表示:(*a)[i]
3.指针函数:即返回值是指针类型的函数
举例说明:
int *comp()
4.函数指针:即指向函数的指针,函数名就是函数指针
举例说明:
int (*comp)()
右左右左法
从变量名开始,先右再左地,交替地一个一个向外看,在纸上写下:“变量是”
若向右遇到左圆括号,在纸上写下:“函数,参数是”,并用同样的方法处理括号中每一个参数——在纸上写下:“返回”
若向右遇到方括号,在纸上写下:“数组,长度为{方括号的内容},元素类型为”
若向右遇到右圆括号,什么也不做
若向左遇到*,在纸上写下:“指针,指向”
若向左遇到任何类型,在纸上写下对应的类型名
举例说明:分析void ((*fp1)(int))[10]
从fp1开始——fp1是
向右,遇到右括号,什么也不做
向左,遇到*——指针,指向
向右,遇到左圆括号——函数,参数是int,返回
向左,遇到*——指针,指向
向右,遇到左方括号——数组,长度为10,元素类型为
向左,遇到*——指针,指向
向右,已经到声明结尾,什么也不做
向左,遇到void——void
结果是:fp1是 指针,指向 函数,参数是int,返回指针,指向数组,长度为10,元素类型为 指针,指向 void
代码在前几周的博客中均有分析
五次实验总结
实验总结
- 嵌入式linux
1.在实验一、二、四、五中我们都需要配置开发环境,那么arm、linux系统、开发板之间的关系是什么?
开发板使用的是嵌入式linux系统,但是在开发板中没有足够的资源运行开发程序和调试工具,此时就需要pc端的linux中的交叉编译、汇编以及连接工具形成可执行的二进制代码,然后把可执行文件下载到开发板上并运行。交叉编译环境的配置在pc端的linux系统中,主编器为:armv4l-unknow-linux-gcc4l.
串行端口主要用于串列式逐位元数据传输,在实验中pc端和开发板通过串行端口的方式链接来传输数据。
“超级终端”的作用作为是调试开发板输出信息的监视器和键盘输入的工具。
2.linux、windows xp、超级终端如何实现文件共享。
linux/linux系统中使用nfs服务。它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件。
在本实验中,通过命令mount -t nfs -o nolock 虚拟机的ip地址:/home/bc /host(超级终端)在超级终端中挂载共享文件夹,实现虚拟机和开发板的通讯。
在Linux与Windows中间文件共享采用SAMBA服务;
本实验步骤中在windows 的cmd中输入命令\虚拟机的ip地址实现虚拟机和windows共享文件的过程就是SAMA服务。(实验中sam服务已经配置好)
- 实验问题及解决方法
(1)配置编译器环境变量的问题
命令 PATH 变量为PATH=$PATH:$HOME/bin:/opt/host/armv4l/bin/注意语句中的“arm4l”中是字母“l”,不是数字“1”.
存盘后执行: source /root/.bash_profile,注意source后面的空格。
(2)在arm中运行可执行文件,执行./hello显示:cannot excute binary file.
因为命令`mount -t nfs -o nolock 虚拟机的ip地址:/home/bc /host(超级终端)将我们将bc文件挂载超级终端的host目录下,所以运行文件时应该在host目录下执行./hello命令。
(3)实验2中,在超级终端运行可执行文件term时出错,提示/dev/ttyS0: No such file or directory。
这个问题是因为在Linux下串口文件位于/dev下,一般在老版本的内核中串口一为/dev/ttyS0,串口二为 /dev/ttyS1, 在我们的开发板中串口设备位于/dev/tts/下,因为开发板中没有ttyS0这个设备,所以我们要建立一个连接。
按照实验指导书说的在超级终端中进入/dev文件夹中,输入命令ln –sf /dev/tts/0 ttyS0(注意空格与字母l、数字0。)
```
- [第一次实践](http://www.cnblogs.com/yayaer/p/6035914.html)
- [第二次实践](http://www.cnblogs.com/yayaer/p/6130446.html)
- [第三次实践](http://www.cnblogs.com/yayaer/p/6082119.html)
- [第四次实践](http://www.cnblogs.com/alovera/p/6105574.html)
- [第五次实践](http://www.cnblogs.com/alovera/p/6059385.html)
## 问题与解决
<font size=3>**1.想想who|sort是怎么实现的。**</font>
who把输出送给stdout,sort从stdin中读入数据,那也就是说who的stdout和sort的stdin连成了一个。
<font size=3>**2.在gdb中详细观察pid的变化**</font>
- 1.对代码testpid.c
![](http://images2015.cnblogs.com/blog/877181/201611/877181-20161128193112693-778646492.png)
- 2.在fork函数中,父进程返回子进程的pid,子进程的pid返回0,可以在gdb中进一步了解这种机制,在代码forkdemo1.c中,由于根据初始输出pid不为0,得知先返回的是父进程。
![](http://images2015.cnblogs.com/blog/877181/201611/877181-20161128195038162-308421375.png)
- 3.可以试着用gdb运行书上第493页的代码:
include "csapp.h"
void unix_error(char *msg)
{
fprintf(stderr,"fork error:%s
",strerror(errno));
exit(0);
}
pid_t Fork()
{
pid_t pid;
if((pid=fork())<0)
unix_error("Fork error");
return pid;
}
int main()
{
pid_t pid;
int x=1;
pid=Fork();
if(pid==0){
printf("child:x=%d
",++x);
exit(0);
}
printf("parent:x=%d
",--x);
}
![](http://images2015.cnblogs.com/blog/877181/201611/877181-20161128200451865-1664672074.png)
在这个例子中,fork函数被父进程调用一次,返回两次——一次返回父进程,一次返回新创建的子进程。其中这两个进程是并发运行的独立进程,它们有相同的用户栈、相同的本地变量值、相同的堆、相同的全局变量值,以及相同的代码,但是却拥有独立的地址空间。
<font size=3>**C语言编程实现who命令**</font>
- who命令是查询当前登录的每个用户,它的输出包括用户名、终端类型、登录日期及远程主机,在Linux系统中输入who命令:
![](http://images2015.cnblogs.com/blog/877181/201612/877181-20161204191854006-1599024617.png)
- 老师在之前给了who1.c的代码:
![](http://images2015.cnblogs.com/blog/877181/201612/877181-20161204192129927-1184870597.png)
- 与who命令相比,时间格式不一样.
- 执行的结果比who命令多了几条,原因是utmp中保存的用户不仅仅是已经登陆的用户,还有系统的其他服务所需要的“用户”,所以在显出所有登陆用户的时候,应该过滤掉其他用户,只保留登陆用户。
- 可以通过```ut_type```来区别,登陆用户的```ut_type```是```USER_PROCESS```
- 编写who代码:
include <stdio.h>
include <stdlib.h>
include <utmp.h>
include <fcntl.h>
include <unistd.h>
include <time.h>
define SHOWHOST
void show_time(long timeval){
char format_time[40];
struct tm *cp;
cp = localtime(&timeval);
strftime(format_time,40,"%F %R",cp);
printf("%s",format_time);
}
int show_info( struct utmp *utbufp )
{
if(utbufp->ut_type == USER_PROCESS){
printf("%-8.8s", utbufp->ut_name);
printf(" ");
printf("%-8.8s", utbufp->ut_line);
printf(" ");
show_time(utbufp->ut_time);
printf(" ");
ifdef SHOWHOST
printf("(%s)", utbufp->ut_host);
endif
printf("
");
}
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, ¤t_record, reclen) == reclen )
show_info(¤t_record);
close(utmpfd);
return 0;
}
- 运行结果如下:
![](http://images2015.cnblogs.com/blog/877181/201612/877181-20161204192545974-105612844.png)
## 代码行数统计
![](http://images2015.cnblogs.com/blog/877181/201612/877181-20161204193029099-284489200.png)
## 学习进度条
| | 代码行数(新增/累积)| 博客量(新增/累积)|学习时间(新增/累积)|重要成长|
| -------- | :----------------:|:----------------:|:---------------: |:-----:|
| 目标 | 5000行 | 30篇 | 400小时 | |
| 第一周 | 0/0 | 1/2 | 10/10 | 使用虚拟机安装linux系统 |
| 第二周 | 341/341 | 1/3 | 20/30 | 掌握核心的linux命令 |
| 第三周 | 177/518 | 2/5 | 16/46 | 学会了虚拟机上的VC编程 |
| 第五周 | 161/679 | 1/6 | 15/61 | |
| 第六周 | 73/752 | 1/7 | 15/76 | 安装了Y86处理器 |
| 第七周 | 134/886 | 1/8 | 12/88 | 建立了项目结构 |
| 第八周 | 0/886 | 2/10 | 12/100 | 进行了系统的复习 |
| 第九周 | 61/947 | 2/12 | 10/110 | 学习Linux操作系统的基本I/O服务 |
| 第十周 | 502/1449 | 2/14 | 10/120 | 通过实践加深了对指令的理解 |
| 第十一周 | 667/2116 | 2/16 | 15/125 | 学习了异常,通过实践了解了进程的并发 |
| 第十二周 | 69/2185 | 4/16 | 15/140 | 通过对前三周代码的复习,加深了对教材内容的认识 |
## 参考资料
- [《深入理解计算机系统V2》学习指导](http://www.cnblogs.com/rocedu/p/5826467.html)