20145308 20145302 《信息安全系统设计基础》实验二 固件设计

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\n");
    	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\n");
		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", n);
    	put(&buffer, n);//将整数存放进缓冲区
	}
  put(&buffer, OVER);
  printf("producer stopped!\n");//生产者进程结束
  return NULL;
}
/*--------------------------------------------------------*/
/* 消费者 */
void * consumer(void * data)
{
  int d;
  while (1) {//无限循环
    d = get(&buffer);//取缓冲区的数据
    if (d == OVER ) break;//缓冲区为空停止
    printf("              %d-->get\n", d);//输出读取数据
  }
  printf("consumer stopped!\n");//消费者进程停止
  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!!!\n");
   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\n");
    while (STOP==FALSE) //不中止
    {
    read(fd,&c,1); /* 读取文件 */
    write(1,&c,1); /* 标准输出 */
    }
    printf("exit from reading modem\n");
    return NULL; 
}
/*--------------------------------------------------------*/
/* 传送 */
void* send(void * data)
{
    int c='0';
    printf("send data\n");
    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\r ");
        return 1;
}
n = write( fd, "hello\r", 6);//写文件操作返回数
if ( n < 0 )//写文件失败
        puts( "write() of 6 bytes failed!\r");
puts( "write() of 6 bytes ok!\r");//否则写文件成功

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库的使用,结合《操作系统》课上讲授的内容,感觉能更好地理解本次实验的内容,同时也加深了对《操作系统》课程知识的学习。

posted @ 2016-11-13 19:17  20145308刘昊阳  阅读(442)  评论(0编辑  收藏  举报