20145308 20145302 《信息安全系统设计基础》实验二 固件设计
北京电子科技学院(BESTI) 实 验 报 告
课程: 深入理解计算机系统 班级: 1453
姓名: (按贡献程度大小排名)刘昊阳 张薇
学号: (按贡献程度大小排名)20145308 20145302
成绩: 指导教师: 娄嘉鹏 实验日期: 11.3
实验密级: 预习程度:
实验时间: 9:50-12:30
仪器组次: 必修/选修: 必修 实验序号: 2
实验名称: 信息安全系统设计基础实验二 固件设计
实验目的与要求: 了解多线程程序设计的基本原理。
学习 pthread 库函数的使用。
实验仪器:
联想电脑 1
Arm开发板 1
实验内容与步骤:
1.Linux使用:先打开桌面 vmware,然后打开C:/redhat 9虚拟机原始文件/redhat.vmx
用户名/密码: root:123456
vmware 与Winxp 切换:ctrl + alt
2.完成 2410经典实验指导20110331.pdf中实验2.3
gcc *.c -l pthread
1.根据实验一配置环境的过程将环境配置好
2.将实验二代码拷贝至共享文件夹
3.在虚拟机中编译代码
4.下载调试,运行可执行文件term
参考资料:
信息安全系统设计基础实验图文教程
知识点理解
1、02_pthread
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "pthread.h"
#define BUFFER_SIZE 16
/* 建立缓冲区 (结构体形式)*/
struct prodcons {
int buffer[BUFFER_SIZE]; /* 缓冲区数组 */
pthread_mutex_t lock; /* 互斥锁,避免进程间的冲突导致结果错误 */
int readpos, writepos; /* 读和写位置 */
pthread_cond_t notempty; /* 缓冲区非空信号 */
pthread_cond_t notfull; /* 非满信号 */
};
/*--------------------------------------------------------*/
/* 缓冲区初始化 */
void init(struct prodcons * b)//结构体类型变量
{
pthread_mutex_init(&b->lock, NULL);//初始化互斥锁
pthread_cond_init(&b->notempty, NULL);//初始化非空和非满信号
pthread_cond_init(&b->notfull, NULL);
b->readpos = 0;//读写初始位置都为0
b->writepos = 0;
}
/*--------------------------------------------------------*/
/* 向缓冲区里存储整数 */
void put(struct prodcons * b, int data)
{
pthread_mutex_lock(&b->lock);//锁上互斥锁
/* 缓冲区非满才能写数据 */
while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
printf("wait for not full
");
pthread_cond_wait(&b->notfull, &b->lock);
}
/* 写数据且写指针加一 */
b->buffer[b->writepos] = data;
b->writepos++;
if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
/* 此时缓冲区非空,设置非空信号 */
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);//释放互斥锁
}
/*--------------------------------------------------------*/
/* 从缓冲区中读取并移动数据 */
int get(struct prodcons * b)
{
int data;
pthread_mutex_lock(&b->lock);//锁上互斥锁
/* 缓冲区非空才能去读数据 */
while (b->writepos == b->readpos) {
printf("wait for not empty
");
pthread_cond_wait(&b->notempty, &b->lock);//等待
}
/* 读数据并且读指针加一 */
data = b->buffer[b->readpos];
b->readpos++;
if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
/* 此时缓冲区非满,设置非满信号 */
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);//释放互斥锁
return data;//返回数据
}
/*--------------------------------------------------------*/
#define OVER (-1)
struct prodcons buffer;
/*--------------------------------------------------------*/
/* 生产者 */
void * producer(void * data)
{
int n;
for (n = 0; n < 1000; n++) {//将0-999,共1000个整数存放在缓冲区
printf(" put-->%d
", n);
put(&buffer, n);//将整数存放进缓冲区
}
put(&buffer, OVER);
printf("producer stopped!
");//生产者进程结束
return NULL;
}
/*--------------------------------------------------------*/
/* 消费者 */
void * consumer(void * data)
{
int d;
while (1) {//无限循环
d = get(&buffer);//取缓冲区的数据
if (d == OVER ) break;//缓冲区为空停止
printf(" %d-->get
", d);//输出读取数据
}
printf("consumer stopped!
");//消费者进程停止
return NULL;
}
/*--------------------------------------------------------*/
int main(void)
{
pthread_t th_a, th_b;
void * retval;
init(&buffer);//初始化缓冲区
pthread_create(&th_a, NULL, producer, 0);
pthread_create(&th_b, NULL, consumer, 0);
/* 消费者和生产者进程结束,先有生产者存数据,再有消费者读数据 */
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
return 0;
}
生产者和消费者进程关系图
2、03_tty
term.c
#include <termios.h> /*PPSIX 终端控制定义*/
#include <stdio.h> /*标准输入输出定义*/
#include <unistd.h> /*linux 标准函数定义*/
#include <fcntl.h> /*文件控制定义*/
#include <sys/signal.h>
#include <pthread.h> /*线程库定义*/
#define BAUDRATE B115200
#define COM1 "/dev/ttyS0"
#define COM2 "/dev/ttyS1"
#define ENDMINITERM1 27 /* ESC 退出 */
#define ENDMINITERM2 3 /*ctl +c 退出 */
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
volatile int fd;
void child_handler(int s)
{
printf("stop!!!
");
STOP=TRUE;//终止程序
}
/*--------------------------------------------------------*/
void* keyboard(void * data)
{
int c;
for (;;){
c=getchar();
// printf("getchar is :%d",c);
if( (c== ENDMINITERM1) | (c==ENDMINITERM2)){//ESC 或 ctrl+c 则退出
STOP=TRUE;
break ;
}
}
return NULL;
}
/*--------------------------------------------------------*/
/* 管理者 */
void* receive(void * data)
{
int c;
printf("read modem
");
while (STOP==FALSE) //不中止
{
read(fd,&c,1); /* 读取文件 */
write(1,&c,1); /* 标准输出 */
}
printf("exit from reading modem
");
return NULL;
}
/*--------------------------------------------------------*/
/* 传送 */
void* send(void * data)
{
int c='0';
printf("send data
");
while (STOP==FALSE)//不停止
{
c++;
c %= 255;
write(fd,&c,1); /* 写文件 */
usleep(100000);
}
return NULL; /* wait for child to die or it will become a zombie */
}
/*--------------------------------------------------------*/
int main(int argc,char** argv)
{
struct termios oldtio,newtio,oldstdtio,newstdtio;
struct sigaction sa;
int ok;
pthread_t th_a, th_b, th_c;
void * retval;
if( argc > 1)
fd = open(COM2, O_RDWR ); /*以读写方式打开串口*/
else
fd = open(COM1, O_RDWR ); //| O_NOCTTY |O_NONBLOCK);
if (fd <0) { /* 不能打开串口一*/
perror(COM1);
exit(-1);
}
tcgetattr(0,&oldstdtio);
tcgetattr(fd,&oldtio); /* save current modem settings */
tcgetattr(fd,&newstdtio); /* get working stdtio */
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; /* 控制模式标志 */
newtio.c_iflag = IGNPAR; /* 输入模式标志 */
newtio.c_oflag = 0; /* 输出模式标志 */
newtio.c_lflag = 0; /* local mode flags */
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
/* 清空 */
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);/*set attrib */
sa.sa_handler = child_handler;
sa.sa_flags = 0;
sigaction(SIGCHLD,&sa,NULL); /* handle dying child */
pthread_create(&th_a, NULL, keyboard, 0);//创建进程
pthread_create(&th_b, NULL, receive, 0);
pthread_create(&th_c, NULL, send, 0);
pthread_join(th_a, &retval);//加入进程
pthread_join(th_b, &retval);
pthread_join(th_c, &retval);
tcsetattr(fd,TCSANOW,&oldtio); /* 存储旧设置 */
tcsetattr(0,TCSANOW,&oldstdtio);
close(fd);/* 关闭文件 */
exit(0);
}
tty.c
#include <stdio.h> /*标准输入输出定义*/
#include <unistd.h> /*linux 标准函数定义*/
#include <fcntl.h> /*文件控制定义*/
#include <errno.h> /*错误号定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
int main()
{
int fd,n;
char buf[256];//数组大小
fd=open("/dev/ttyS1",O_NOCTTY|O_RDWR|O_NONBLOCK); /*以读写方式打开串口*/
if( fd < 0) /* 不能打开串口一*/
{
perror("Unable open /dev/ttyS0
");
return 1;
}
n = write( fd, "hello
", 6);//写文件操作返回数
if ( n < 0 )//写文件失败
puts( "write() of 6 bytes failed!
");
puts( "write() of 6 bytes ok!
");//否则写文件成功
while(1)
{
read(fd,buf,256);
puts(buf);
if(strncmp(buf,"quit",4)==0)break;
}
return 0;
}
int set_port(int fd)
{
struct termios opt;
tcgetattr(fd,&opt);/* 获得当前选项设置 */
show_option(&opt);
// opt.c_cflags &=
tcsetattr(fd,&opt);/*get current option setup*/
}
串口通讯实验流程图
实验问题与解决:
1、无法运行
重新输入命令“mount -t nfs -o nolock 192.168.0.234:/home/bc /host”将共享文件挂载好就可以运行了
2、执行./term出现错误,按照指导书上的解决方式操作之后还是出错
后来发现输命令行时没有输入-sf
后面的空格,输入后就解决了问题
3、02_pthread程序理解,如何理解互斥锁
本来看不懂的代码,后来结合操作系统课上讲的生产者和消费者进程的执行关系,理解了同一个数据库中不可能允许两个进程同时读写数据,所以一定会有进程锁的概念。利用一个信号量,在任意一个进程开始前,首先检查进程锁是否锁住,没有锁住才能执行,进程执行前要设置信号量(进程锁)以通知其他进程不能执行;结束进程时也要设置信号量(解开进程锁),以便其它进程可以运行。从而避免进程之间出现冲突,导致读写数据结果出现错误。
实验体会:
在这一次实验中,我们学习了多线程程序设计的原理,还学习了pthread库的使用,结合《操作系统》课上讲授的内容,感觉能更好地理解本次实验的内容,同时也加深了对《操作系统》课程知识的学习。