天天看點

20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

實驗報告封面

20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

實驗内容與步驟

1、開發環境的配置同實驗一。

2、将實驗代碼拷貝到共享檔案夾中。

20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

3、在虛拟機中編譯代碼。

  • 對于多線程相關的代碼,編譯時需要加-lpthread的庫。
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

4、下載下傳調試

  • 在超級終端中運作可執行檔案pthread,可得實驗結果如圖所示。
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
  • 運作可執行檔案term。
  • 注意:如果在執行./term 時出現下面的錯誤

    /dev/ttyS0: No such file or directory

  • 可以通過方法建立一個連接配接來解決。
    • 在 Linux 下序列槽檔案位于/dev 下,一般在老版本的核心中序列槽一為/dev/ttyS0 ,序列槽二為 /dev/ttyS1, 在我們的開發闆中序列槽裝置位于/dev/tts/下,因為開發闆中沒有ttyS0這個裝置,是以我們要建立一個連接配接。
    • 首先在超級終端中進入/dev檔案夾中。
    • 輸入指令“ln –sf /dev/tts/0 /dev/ttyS0” 注意空格與字母l、數字0。
  • 成功,得到實驗結果。
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

實驗中遇到的問題和解決方法

問題1:

  • 在虛拟機中編譯代碼時第一次沒有編譯成功:command not found
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
  • 解決方法:
    • 在又重新輸入指令行,排除是輸入錯誤的因素。我們試着重新配置了環境:
      • vi /root/.bash_profile
      • source /root/.bash_profile
        20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
  • 成功
  • 檔案03_tty遇到同樣的問題,配置後同樣成功問題解決
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發

問題2:

  • 在終端執行./term時出現錯誤
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
  • 解決方法:根據實驗指導書輸入指令“ln –sf /dev/tts/0 /dev/ttyS0” 注意空格與字母l、數字0。
    20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
  • 運作成功實驗二完成

源代碼注釋

(一)線程代碼分析

#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;
	    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->notfull,不滿則跳出阻塞
	    }
	
	    /*寫資料并且指針前移*/
	    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);//等待狀态變量 b->notempty,不空則跳出阻塞。否則無資料可讀。
	    }
	
	    /* 讀資料并且指針前移 */
	    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;
	
	/*實作一個生産者程式:生産者線程不斷順序地将0到1000的數字寫入共享的循環緩沖區,當生産-1時,程式終止。*/
	void * producer(void * data)
	{
	    int n;
	    for (n = 0; n < 1000; n++) {
	        printf(" put-->%d\n", n);
	        put(&buffer, n);
	    }
	    put(&buffer, OVER);
	    printf("producer stopped!\n");
	    return NULL;
	}
	
	/*消費掉緩存中生産出來的資料:消費者線程不斷地從共享的循環緩沖區讀取資料,當消費-1時,程式終止*/
	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;
	}
           

(二)串行口代碼分析

  • 打開序列槽是通過标準的檔案打開函數來實作的
int fd;
	fd = open( "/dev/ttyS0", O_RDWR); /*以讀寫方式打開序列槽*/
	if (-1 == fd)/* 不能打開序列槽一*/
	{ 
	    perror(" 提示錯誤!");
	}
           
  • 序列槽設定
最基本的設定序列槽包括波特率設定,效驗位和停止位設定。序列槽的設定主要是設定struct termios結構體的各成員值。
	
	- 波特率設定:
	    struct termios Opt;
	    tcgetattr(fd, &Opt);
	    cfsetispeed(&Opt,B19200); /*設定為 19200Bps*/
	    cfsetospeed(&Opt,B19200);
	    tcsetattr(fd,TCANOW,&Opt);
	
	- 校驗位和停止位的設定:
	    無效驗 8 位
	    Option.c_cflag &= ~PARENB;Option.c_cflag &= ~CSTOPB;Option.c_cflag &= ~CSIZE;Option.c_cflag |= ~CS8;
	    奇效驗(Odd) 7 位
	    Option.c_cflag |= ~PARENB;Option.c_cflag &= ~PARODD;Option.c_cflag &= ~CSTOPB;Option.c_cflag &= ~CSIZE;Option.c_cflag |= ~CS7;
	    偶效驗(Even) 7 位
	    Option.c_cflag &= ~PARENB;Option.c_cflag |= ~PARODD;Option.c_cflag &= ~CSTOPB;Option.c_cflag &= ~CSIZE;Option.c_cflag |= ~CS7;
	    Space 效驗 7 位
	    Option.c_cflag &= ~PARENB;Option.c_cflag &= ~CSTOPB;Option.c_cflag &= &~CSIZE;Option.c_cflag |= CS8;
	
	- 設定停止位:
	    1 位:options.c_cflag &= ~CSTOPB;
	    2 位:options.c_cflag |= CSTOPB;
	
	注:如果不是開發終端,隻是序列槽傳輸資料,而不需要序列槽來處理,那麼使用原始模式(Raw Mode) 方式來通訊,設定方式如下:
	    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
	    options.c_oflag &= ~OPOST; /*Output*/
           
  • 讀寫、關閉序列槽
設定好序列槽之後,讀寫序列槽就很容易了,把序列槽當作檔案讀寫就可以了。
	
	- 發送資料:
	    char buffer[1024];
	    int Length=1024;
	    int nByte;
	    nByte = write(fd, buffer ,Length)
	
	- 讀取序列槽資料:
	使用檔案操作read函數讀取,如果設定為原始模式(Raw Mode)傳輸資料,那麼read函數傳回的字元數是實際序列槽收到的字元數。可以使用操作檔案的函數來實作異步讀取,如 fcntl,或者select等來操作。
	    char buff[1024];
	    int Len=1024;
	    int readByte = read(fd, buff, Len);
	
	- 關閉序列槽就是關閉檔案。
	    close(fd);
           

實驗感想與體會

通過這次實驗,我們對環境開發的了解又近了一步。有了實驗一的操作經驗,在完成實驗二時避免走了很多彎路,練習起來更加熟練。這次實驗最大的收獲是遇到問題我們能自己探索解決,更深刻的了解并掌握了相關知識點。希望今後的實驗我們能完成的更加完善與熟練。

隊友連結:http://www.cnblogs.com/sjy519/p/6076699.html