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

  • 相关阅读:
    第三套三
    多线程读写共享变量时,synchronized与volatile的作用
    jQuery源代码学习笔记:构造jQuery对象
    写入位置时发生訪问冲突
    Free Editor
    大区间素数筛选 POJ2689
    HDU
    CentOS下挂载U盘
    得到当前堆栈信息的两种方式(Thread和Throwable)的纠结
    [实战]MVC5+EF6+MySql企业网盘实战(9)——编辑文件名
  • 原文地址:https://www.cnblogs.com/yg961022/p/6059547.html
Copyright © 2020-2023  润新知