Trung tâm đào tạo thiết kế vi mạch Semicon


  • ĐĂNG KÝ TÀI KHOẢN ĐỂ TRUY CẬP NHIỀU TÀI LIỆU HƠN!
  • Create an account
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
wafer.jpg

Lập trình với luồng (Thread)

E-mail Print PDF

1. Mục đích

- Tìm hiểu về luồng (thread) trên Linux, và cơ chế lập trình ứng dụng đa luồng (mutlithreads).

2. Chuẩn bị

- PC Linux (Ubuntu) with arm-linux-gcc

- Bộ KIT thực hành FriendlyArm mini/macro2440

3. Nội dung thực hành

3.1. Cơ bản về tạo luồng

Viết ứng dụng đơn giản thực hiện tạo luồng (dùng hàm pthread_create).

Ứng dụng minh họa cách tạo luồng và truyền hàm xử lý của luồng.

(Listing: thread1.c)

//example 1: Create a thread

#include <stdio.h>

#include <pthread.h>

void* printx(void* unused)

{

          while(1)

          {

                   fputc('x',stdout); //Hàm xử lý của luồng in ký tự 'x'

          }

          return NULL;      

}

int main(int argc, char** argv)

{

pthread_t thread_id;

pthread_create(&thread_id, NULL, &printx, NULL); //Tạo luồng

while(1)

{

           fputc('o',stdout); //Luồng chính liên tục in ra ký tự 'o'

}

return 0;

}

Biên dịch và chạy ví dụ này trên PC hoặc trên KIT và quan sát kết quả.

(Chú ý: Luồng chính liên tục in ký tự 'o', luồng tạo ra liên tục in ký tự 'x', kết quả các ký tự o, x xen kẽ phụ thuộc vào các luồng được hệ điều hành lập lịch cho 

chạy)

3.2. Truyền dữ liệu cho luồng

Ví dụ tiếp theo minh họa hàm xử lý của luồng có tham số đầu vào, vì vậy cần tổ chức truyền tham số cho hàm này theo cách thức qui định

Chú ý: Hàm xử lý của luồng có kiểu tham số là void*, vì vậy để truyền nhiều thành phần dữ liệu cho luồng cần tạo một cấu trúc (struct), và truyền cho hàm xử lý 

của luồng tham số là biến cấu trúc này.

Nguyên mẫu hàm xử lý của luồng có dạng: void* thread_function(void* params)   (Được khai báo là hàm toàn cục)

Ví dụ sau minh họa tạo ra 2 luồng cùng sử dụng 1 hàm xử lý in một số lượng ký tự ra màn hình, với tham số truyền vào là ký tự và số lượng muốn in.

(Listing: thread2.c)

//example 2: create 2 threads

#include <pthread.h>

#include <stdio.h>

//parameters to print function

struct char_print_parms

{

            char character; //character to print

            int count; // times to print

};

//Ham xu ly cua thread

//In ky tu ra man hinh, duoc cho boi tham so la mot con tro den cau truc du lieu tren

void* char_print(void* params)

{

            struct char_print_parms* p = (struct char_print_parms*) params; //ep kieu tham so truyen vao

            int i;

            int n = p->count; //Bien chua so lan in ra

            char c=p->character; //Bien chua ma ky tu muon in ra

            for(i=0;i<n;i++)

                        fputc(c,stdout); //Ham in 1 ky tu ra thiet ra chuan

            return NULL;

}

int main(int argc, char** agrv)

{

            pthread_t  thread1_id, thread2_id; //2 bien doi tuong thread

            struct char_print_parms  p1, p2; //2 bien tham so truyen cho ham xu ly cua thread

            //Tao 1 thread in 30000 chu 'x'

            p1.character = 'x';

            p1.count = 30000;

            pthread_create(&thread1_id, NULL, &char_print, &p1);

            //Tao 1 thread khac in ra 20000 chu 'o'

            p2.character = 'o';

            p2.count = 20000;

            pthread_create(&thread2_id, NULL, &char_print, &p2);

            //Dam bao thread1 da ket thuc

            pthread_join(thread1_id, NULL);

            //Dam bao thread2 da ket thuc

            pthread_join(thread2_id, NULL);

            // Now we can safely return.

            return 0;

}

Biên dịch và chạy ví dụ trên trên máy tính hoặc KIT và quan sát kết quả.

3.3. Bài tập kết hợp giao tiếp button, led trên KIT sử dụng đa luồng

Mục đích: Áp dụng cơ chế đa luồng, viết một ứng dụng trên KIT thực hiện hiệu ứng led đuổi, sử dụng nút bấm K1, K2 để thay đổi (giảm/tăng) tốc độ của hiệu 

ứng led đuổi.

Chú ý:

-         - Chương trình gồm một luồng chính (master thread) thực hiện hiệu ứng led đuổi trong một vòng lặp vô hạn, hiệu ứng dựa trên viết bật/tắt từng led với thời

           gian trễ (delay) thích hợp (giả sử là t milisecond, ban đầu mặc định là 1000ms=1s)

-         - Thời gian trễ nói trên có thể điều chỉnh (tăng/giảm thích hợp) khi bấm nút K1, K2.

-         Vì button device driver cho phép giao tiếp kiểu thăm dò (polling), cần sử dụng một luồng riêng để thực hiện công việc này (song song với công việc chính là 

           điều khiển hiệu ứng nháy led), hàm xử lý của luồng sẽ đọc K1, K2 có được ấn để thay đổi giá trị t tương ứng.

Tiến hành: Tham khảo mã nguồn ví dụ sau

(Listing: threadbuttonled.c)

/*    Example 3. Programming threads. ARM LINUX COURSE                     */

/**********************************************************

* Chuong trinh:

* main: Thuc hien dieu khien led chay duoi

* thread: Thuc hien doc trang thai (polling) nut bam de thay doi toc do led

***********************************************************/


#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/ioctl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/select.h>

#include <sys/time.h>

#include <errno.h>


#define ON  1

#define OFF 0


/* Bien luu thoi gian delay */

// Thay doi khi K1, K2 duoc an 


static int t = 1000; //don vi la milisecond, ban dau mac dinh la 1000 ms

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;



/* Ham sleep ms su dung usleep cua linux */ 

void sleepms(int ms)

{

//usleep in us, sleep in second

usleep(1000*ms); //convert to microseconds

return;

};

/* Cau truc du lieu se truyen tham so cho thread */

struct thread_parms

{

char btn[6];

int btn_fd;

};


/* Ham xu ly cua thread thuc hien doc nut K1, K2 (polling) */

void* btn_polling(void* param);


int main(int argc, char** agrv)

{

int led_fd, button_fd; //# of device file 

struct thread_parms p; //Bien cau truc chua tham so se truyen cho ham xu ly cua thread

pthread_t thread_id;   //# of thread


int led_no; //So hieu led 0-4

//Mang chua gia tri trang thai 6 button se doc

char buttons[6] = {'0', '0', '0', '0', '0', '0'}; 

int i; 

//Mo thiet bi (led port), can kiem tra chinh xac ten trong /dev

led_fd = open("/dev/leds", 0);

if (led_fd < 0) {

perror("open device leds");

exit(1);

}

else printf("open device led ok\n");

//Mo thiet bi (button port)

button_fd = open("/dev/buttons", 0); //mo button port

if(button_fd < 0) 

{

perror("open device buttons");

exit(1);

}

else printf("open device button ok\n");


//Chuan bi tham so truyen vao cho ham xu ly cua thread

p.btn_fd = button_fd; // button device file number

//memset(p.btn, '0', sizeof(p.btn)); //khoi tao buffer 

for(i=0;i<6;i++) p.btn[i]='0'; //buffer to read button status (K1-K6)


//Tao thread thuc hien polling button

thread_id = pthread_create(&thread_id, NULL, &btn_polling, &p);

//Chuong trinh chinh (master thread) thuc hien hieu ung led duoi

//voi thoi gian delay chua trong bien t

//Ban dau tat ca cac led deu off

for(i=0;i<4;i++) ioctl(led_fd, OFF, i);

led_no=0;

while(1)

{

//Bat led led_no

ioctl(led_fd, ON, led_no);

//Sleep in t ms

sleepms(t); 

//Tat led led_no va chuan bi bat luon led ke tiep

ioctl(led_fd, OFF, led_no);

led_no++;

if(led_no == 4) led_no = 0;

}

close(button_fd);

close(led_fd);

return 0;

}


void* btn_polling(void* param)

{

struct thread_parms* p = (struct thread_parms*)param;

char cur_btn[6], old_btn[6];

int btn_fd;

int i;

for(i=0;i<6;i++) old_btn[i] = p->btn[i];

btn_fd = p->btn_fd; 

for(;;)//Lien tuc tham do trang thai nut bam (K1, K2 co duoc an)

{

int num=read(btn_fd, cur_btn, sizeof(cur_btn));

if(num != sizeof(cur_btn))

{

perror("read buttons:");

exit(1);

}

//Chi can doc K1, K2 tuong ung voi tang/giam led speed

//Doc K1

if(old_btn[0] != cur_btn[0])

{

old_btn[0] = cur_btn[0];

printf("K1 is pressed/released\n");

//Can dung mutex cho bien t ?

pthread_mutex_lock( &mutex1 );

t = t+50; //tang thoi gian delay

pthread_mutex_unlock( &mutex1 );

}

//Doc K2

if(old_btn[1] != cur_btn[1])

{

old_btn[1] = cur_btn[1];

printf("K2 is pressed/released\n");

//Can dung mutex cho bien t ?

pthread_mutex_lock( &mutex1 );

t = t-50; //giam thoi gian delay

if(t < 100) t = 100;

pthread_mutex_unlock( &mutex1 );

}

}

return NULL;

Nguồn https://sites.google.com

Bạn có đam mê ngành thiết kế vi mạch và bạn muốn có mức lương 1000 usd cùng lúc bạn

đang muốn tìm một Trung tâm để học vậy hãy đến với ngành vi mạch tại SEMICON

  HotLine: 0972 800 931 Ms Duyên

 

 

 

 

 

Last Updated ( Monday, 26 October 2015 10:58 )  

Related Articles

Chat Zalo