20145216 20145330 《資訊安全系統設計基礎》 實驗二 固件開發
實驗報告封面
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CO2ETM0MDO0gTMtQjM2ADN3QDMyITMxEjNxAjMtIDN0YDO48CXxEjNxAjMvwlM0QjN4gzLcd2bsJ2Lc12bj5ycn9Gbi52YuUTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
實驗内容與步驟
1、開發環境的配置同實驗一。
2、将實驗代碼拷貝到共享檔案夾中。
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);
實驗感想與體會
通過這次實驗,我們對環境開發的了解又近了一步。有了實驗一的操作經驗,在完成實驗二時避免走了很多彎路,練習起來更加熟練。這次實驗最大的收獲是遇到問題我們能自己探索解決,更深刻的了解并掌握了相關知識點。希望今後的實驗我們能完成的更加完善與熟練。