510 likes | 793 Views
Thực hành Unix, Linux (3) Ngô Thanh Nguyên Bộ môn Hệ thống và Mạng máy tính Khoa Khoa học và kỹ thuật máy tính Email: ntnguyen@cse.hcmut.edu.vn. Lập trình trên Linux. Lập trình IPC dùng shared memory Cơ bản về lập trình POSIX pthread
E N D
Thực hành Unix, Linux (3) Ngô Thanh Nguyên Bộ môn Hệ thống và Mạng máy tính Khoa Khoa học và kỹ thuật máy tính Email: ntnguyen@cse.hcmut.edu.vn Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình trên Linux • Lập trình IPC dùng shared memory • Cơ bản vềlập trình POSIX pthread • Giải quyết tranh chấp trên POSIX thread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình trên Linux • Lậptrình IPC dùng shared memory • Cơ bản vềlập trình POSIX pthread • Giải quyết tranh chấp trên POSIX thread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Giao tiếp và đồng bộ Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Shared memory Process 1 Process 1 xy Process 2 Process 2 xy xy Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Shared memory • Cóthểtheodõitrạngtháibằnglệnhipcs, ipcs -a, ipcs -m • Loại bỏmột shared memory bằnglệnhipcrmshmshm_id,ipcrm -mshm_id $ipcs ------Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 644 110592 11 dest ------Semaphore Arrays -------- key semid owner perms nsems status ------Message Queues -------- key msqid owner perms used-bytes messages Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Shared memory • Cho phép nhiều process dùng chung một vùng bộnhớ • Kích thước tối thiểu/tối đa của vùng là1byte/4MB • Sốvùng nhớchia sẻtối đa trong toàn hệthống: 4096 • Cách sử dụng • Vùng nhớchia sẻphải được tạo ra trước • Process phải gắn vùng nhớchia sẻvào không gian địa chỉcủa mình trước khi sửdụng. • Sau khi dùng xong cóthểgỡvùng nhớchia sẻra khỏi không gian địa chỉcủa process Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Thaotácvới shared memory • Tạo shared memory shmget() • Lấy hoặc thay đổi thuộc tính của shared memory shmctl() • Gắn shared memory vào address space của process shmat() • Gỡshared memory khỏi không gian địa chỉcủa process shmdt() Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Hàm shmget() • Tạomột shared memory #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> intshmget(key_tkey,intsize,intshmflg); • key: key tươngứngvới shared memory • size: kích thước (tính theo đơn vịbyte) • shmflg: tương tự nhưsemflgcủasemget(), nhưng không cóIPC_EXCL • Vídụ shm_id = shmget(123, 4096, IPC_CREAT | 0660) Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Hàm shmat() • Gắn shared memory vào address space của process #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> void *shmat(int shmid, void *shmaddr, int shmflg); • shmid: shared memory ID trả về từ hàm shmget() • shmaddr: địa chỉ nơi gắn vùng nhớchia sẻ • shmflg: SHM_RDONLY (read-only) hoặc 0 Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Hàm shmdt() • Gỡshared memory khỏi không gian địa chỉcủa process #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmdt(void *shmaddr); • shmaddr:địa chỉ nơi gắn vùng nhớchia sẻ (chính làkết quảtrảvềtừhàmshmat()) Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Hàm shmctl() • Lấy thông tin và thay đổi thuộc tính #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, structshmid_ds *buf); • shmid: shared memory ID trả về từ hàm shmget(). • cmd: IPC_STAT, IPC_SET and IPC_RMID Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ • Tạo shared memory 128 bytes • Hai process dùng chung shared memory • Process thứ nhất ghi 2 integer vào shared memory • Process thứ hai đọc từshared meomory vàghi tổng hai sốvào shared memory • Process thứnhất đọc tổng vàhiển thịra Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (shm.c) int main() { int *shm, shmid, k; shmid = shmget(IPC_PRIVATE,128,IPC_CREAT|0666); shm = (int*) shmat(shmid,0,0); if(fork()==0) { /*child*/ shm[0]=111; shm[1]=999; sleep(3); pintf("Process %d reads: Sum = %d", getpid(),shm[2]); shmdt((void *)shm); shmctl(shmid, IPC_RMID, (structshmid_ds *)0); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (shm.c) } else { /*parent*/ sleep(1); printf("Process %d writes to shared memory ...\n", getpid()); shm[2]=shm[0]+shm[1]; shmdt((void *)shm); } return(0); } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình trên Linux • Lậptrình IPC dùng shared memory • Cơ bản vềlập trình POSIX pthread • Giải quyết tranh chấp trên POSIX thread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Giới thiệu về thread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Giới thiệu về thread CODE CODE DATA DATA STACK STACK STACK STACK Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Các chuẩn về thread • POSIX (Portable Operating System Interface) thread hay còn gọi là IEEE 1003.1, 1003.1c • phổ biến trong các hệ thống *NIX hiện tại • đặc tảcác giao diện lập trình API và thư viện user-level thread • Sun Thread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread • Khởitạo thread mới #include <pthread.h> intpthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); • Kếtquảtrảvề • 0: Thànhcông, tạo thread mới, thamsốthreadchứa thread ID • <>0: Thấtbại (mãlỗitrảvềchứatrongbiếnngoàierrno) Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread • Lưu ý vềtham sốthứ3 start_routine • nên có kiểu trả về là con trỏ kiểu void, nếu không thì phải có type casting khi gọi pthread_create(). • nên cómột tham sốkiểu con trỏvoid. Tham sốcủa hàm start_routinesẽ được truyền vào thông qua tham sốthứ4 của hàm pthread_create(). • Lưu ý vềtham sốthứ4 arg • là tham số truyền vào cho hàm start_routine • nếu cần truyền nhiều hơn 1 tham sốthì nên định nghĩa arglàkiểu cấu trúc struct Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread • Thread kết thúc thực thi khi • hàm start_routine kết thúc • cólời gọi hàm pthread_exit()tường minh. • thread bị ngắt bởi lời gọi hàm pthread_cancel() • process chính kết thúc • một trong các thread gọi system call exec() • Lời gọi hàm kết thúc thread tường minh void pthread_exit(void * retval); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ pthcreate.c #include <pthread.h> #include <stdio.h> void* func(void* arg) { inti; for (i = 0; i < 2; i++) { printf ("This is thread %d\n", *((int*)arg)); sleep (1); } } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (tt) int main (int argc, char **argv) { int i; pthread_t tid[3]; for (i=0; i<3; i++){ pthread_create(&tid[i], NULL, func, (void*)&tid[i]); } sleep (5); return 0; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (tt) • Biên dịch và thực thi $gcc pthcreate.c -o pthcreate -lpthread $./pthcreate This is thread -1208886368 This is thread -1219376224 This is thread -1229866080 This is thread -1208886368 This is thread -1219376224 This is thread -1229866080 Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Các hàm lập trình khác • PTHREAD_JOIN #include <pthread.h> int pthread_join(pthread_t th, void **thread_return); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ pthjoin.c #include <pthread.h> #include <stdio.h> void* func(void* arg) { inti; for (i = 0; i < 2; i++) { printf("This is thread %d\n", *((int*)arg)); sleep(1); } } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (tt) int main(int argc, char **argv) { int i; pthread_t tid[3]; for (i=0; i<3; i++){ pthread_create(&tid[i], NULL, func, (void*)&tid[i]); pthread_join(tid[i], NULL); } return 0; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (tt) • Biên dịch và thực thi $gcc pthjoin.c -o pthjoin -lpthread $./pthjoin This is thread -1208710240 This is thread -1208710240 This is thread -1208710240 This is thread -1208710240 This is thread -1208710240 This is thread -1208710240 Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Truyền dữ liệu cho thread charprint.c #include <pthread.h> #include <stdio.h> struct char_print_parms { char character; int count; }; Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Truyềndữliệucho thread (2) void* char_print (void* args) { struct char_print_parms* p = (struct char_print_parms*) args; int i; for (i=0; i<p->count; i++) printf ("%c\n", p->character); return NULL; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Truyềndữliệucho thread (3) int main () { pthread_t tid; struct char_print_parms th_args; th_args.character = 'X'; th_args.count = 5; pthread_create(&tid,NULL,&char_print, &th_args); pthread_join (tid, NULL); return 0; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Truyềndữliệucho thread (4) • Biên dịch và thực thi $gcc charprint.c -o charprint -lpthread $./pthjoin X X X X X Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Lập trình trên Linux • Lập trình IPC dùng shared memory • Cơ bản vềlập trình POSIX pthread • Giải quyết tranh chấp trên POSIX thread • MUTEX • Conditional variable • POSIX semaphore Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
MUTEX • Tương tựsemaphore, MUTEX cung cấp cách thức loại trừ tương hỗ(mutual exclusion) giữa các pthread Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Sử dụng MUTEX #include <pthread.h> pthread_mutex_t mutex; mutex = PTHREAD_MUTEX_INITIALIZER; mutex=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; int pthread_mutex_init( pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
MUTEX Attribute #include <pthread.h> intpthread_mutexattr_init( pthread_mutexattr_t *attr); typedef struct { int __mutexkind; } pthread_mutexattr_t; • Các giátrịcóthểcócủa__mutexkindvà ý nghĩa • PTHREAD_MUTEX_FAST • PTHREAD_MUTEX_RECURSIVE • PTHREAD_MUTEX_ERRORCHECK Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Đồng bộ pthread int pthread_mutex_lock( pthread_mutex_t *mutex); int pthread_mutex_unlock( pthread_mutex_t *mutex); int pthread_mutex_trylock( pthread_mutex_t *mutex); int pthread_mutex_destroy( pthread_mutex_t *mutex); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ mutex.c #include <pthread.h> pthread_mutex_t mutex; int count; void* func(void *arg) { pthread_mutex_lock(&mutex); printf("This is thread %d\n“,*(int*)arg); printf("count = %d\n", count++); sleep(1); pthread_mutex_unlock(&mutex); } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (2) int main(int argc, char **argv) { int i; pthread_t tid[5]; count=0; pthread_mutex_init(&mutex, NULL); for (i=0; i<5; i++) pthread_create(&tid[i], NULL, func, (void*)&tid[i]); for(i=0; i<5; i++) pthread_join(tid[i], NULL); return 0; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (3) • Biên dịch và thực thi $gcc mutex.c -o mutex -lpthread $./mutex This is thread -1250002016 count = 0 This is thread -1208042592 count = 1 This is thread -1218532448 count = 2 Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Conditional variable • Hoạt động theo cơ chếwait-signal, cho phép một hoặc nhiều thread chờmột sựkiện nào đóphát sinh, khi cósựkiện thìcác thread đang chờsẽ được kích hoạt đểthực thi • Phải dùng kèm với mutex Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Conditional variable • Khai báo vàkhởi động #include <pthread.h> pthread_cond_t dk; dk = PTHREAD_COND_INITIALIZER; int pthread_cond_init( pthread_cond_t *cond, pthread_condattr_t *cond_attr); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Conditional variable • Thao tác #include <pthread.h> int pthread_cond_signal( pthread_cond_t *cond); int pthread_cond_broadcast( pthread_cond_t *cond); int pthread_cond_destroy( pthread_cond_t *cond); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Conditional variable • Thao tác #include <pthread.h> int pthread_cond_wait( pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait( pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ cond.c #include <pthread.h> #include <stdio.h> int count = 0; pthread_mutex_t mutex; pthread_cond_t cond; Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (2) void *func(void *arg) { int i; int tnum=*(int*)arg; for (i=0; i<tnum; i++) { pthread_mutex_lock(&mutex); printf("%d %d Holding mutex\n",tnum,i); if (++count==3) { pthread_cond_signal(&cond); printf("%d Signal raised.\n",tnum); } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (3) if (count==1) { printf("%d Waiting signal...\n",tnum); pthread_cond_wait(&cond, &mutex); printf("%d Signal received.\n",tnum); } printf("%d %d Released mutex.\n",tnum,i); pthread_mutex_unlock(&mutex); sleep(1); } } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (4) int main (int argc, char *argv[]) { int i, tnum[2]={1,2}; pthread_t tid[2]; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); for (i=0; i<2; i++) pthread_create(&tid[i],NULL,func,(void*)&tnum[i]); for (i=0; i<2; i++) pthread_join(tid[i], NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0; } Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM
Ví dụ (5) $gcc cond.c –o cond -lpthread $./cond 1 0 Holding mutex 1 Waiting signal... 2 0 Holding mutex 2 0 Released mutex. 2 1 Holding mutex 2 Signal raised. 2 1 Released mutex. 1 Signal received. 1 0 Released mutex. Khoa KH&KTMT - Đại học Bách Khoa Tp. HCM