Cơ bản về lập trình POSIX pthread
Lập trình IPC dùng signal, pipe, shared memory
Giải quyết tranh chấp bằng SVR4 semaphore
Giải quyết tranh chấp trên POSIX thread (tự đọc thêm)
71 trang |
Chia sẻ: haohao89 | Lượt xem: 3352 | Lượt tải: 4
Bạn đang xem trước 20 trang tài liệu Thực hành Unix, linux: Lập trình trên Linux, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Thực hành UNIX/Linux
- phần 3 -
3.2
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình trên Linux (2)
Cơ bản về lập trình POSIX pthread
Lập trình IPC dùng signal, pipe, shared memory
Giải quyết tranh chấp bằng SVR4 semaphore
Giải quyết tranh chấp trên POSIX thread (tự đọc
thêm)
Tài liệu tham khảo
1. John Shapley Gray: Interprocess Communications in Linux : The
Nooks & Crannies, Prentice Hall PTR (2003)
3.3
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Giới thiệu về thread
3.4
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Giới thiệu về thread (t.t)
Các thread trong cùng một process thì chia sẻ các phần sau
z mã (text section)
z dữ liệu (data section)
z các file descriptors
Các vùng riêng của mỗi thread
z Thread ID
z Stack
z Thanh ghi
3.5
Khoa Công nghệ Thông tin - Đạ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
z phổ biến trong các hệ thống *NIX hiện tại
z đặc tả các giao diện lập trình API và thư viện user-level thread
Sun Thread
3.6
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread (1)
Khởi tạo thread mới
#include
int pthread_create (pthread_t * thread, pthread_attr_t * attr,
void * (*start_routine)(void *), void * arg);
Kết quả trả về của hàm
z Thành công, tạo thread mới: 0, tham số thread chứa thread ID
z Thất bại: 0 (mã lỗi trả về chứa trong biến ngoài errno)
Các tham số
z thread: là biến con trỏ kiểu pthread_t, chứa ID của thread mới
z attr: chứa các thiết lập thuộc tính cho thread, nếu tham số attr =
NULL thì thiết lập theo giá trị mặc định.
z start_routine: là tham chiếu đến một hàm của user định nghĩa.
Hàm này chứa đoạn mã thực thi cho thread mới.
z arg: tham số truyền vào cho hàm start_routine.
3.7
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread (2)
Lưu ý về tham số thứ 3 start_routine
z 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().
z nên có một tham số kiểu con trỏ void. Tham số của hàm
start_routine sẽ đượ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
z là tham số truyền vào cho hàm start_routine
z nếu cần truyền nhiều hơn 1 tham số thì nên định nghĩa arg là kiểu
cấu trúc struct
3.8
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình POSIX thread (3)
Thread kết thúc thực thi khi
z hàm start_routine kết thúc
z có lời gọi hàm pthread_exit() tường minh.
z thread bị ngắt bởi lời gọi hàm pthread_cancel()
z process chính kết thúc
z 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);
3.9
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ về lập trình POSIX thread
File thr1.c
1. #include
2. #include
3. void* func(void* arg)
4. {
5. int i;
6. for (i = 0; i < 2; i++) {
7. printf ("This is thread %d\n", *((int*)arg));
8. sleep (1);
9. }
10.}
11.int main (int argc, char **argv) {
12. int i;
13. pthread_t tid[5];
14. for (i = 0; i < 5; i++){
15. pthread_create (&tid[i], NULL, func, (void*)&tid[i]);
16. }
17. sleep (5);
18. return 0;
19.}
3.10
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ về lập trình POSIX thread (t.t)
Biên dịch và thực thi
$gcc thr1.c -o thr1 -lpthread
$./thr1
This is thread 1026
This is thread 2051
This is thread 3076
This is thread 4101
This is thread 5126
This is thread 1026
This is thread 2051
This is thread 3076
This is thread 4101
This is thread 5126
chỉ định liên kết với
thư viện POSIX pthread
3.11
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ về lập trình POSIX thread (t.t)
Chú ý quan trọng khi lập trình lập trình POSIX
z Phải có chỉ thị #include trong chương trình
z Khi biên dịch phải có chỉ định liên kết với thư viện POSIX pthread bằng tùy
chọn -lpthread của GCC (một số version GCC mới có thể đã có thiết lập
mặc định này nên dù user không chỉ định vẫn biên dịch được)
$gcc thr1.c -o thr1
/tmp/cc1PSqgE.o: In function `main':
/tmp/cc1PSqgE.o(.text+0x86): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
z Có thể dùng lệnh ldd để kiểm tra xem file thực thi tạo ra là thr1 phụ thuộc
thư viện nào
$ldd thr1
libpthread.so.0 => /lib/i686/libpthread.so.0 (0x40028000)
libc.so.6 => /lib/i686/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
3.12
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Các hàm lập trình khác
PTHREAD_JOIN
#include
int pthread_join(pthread_t th, void **thread_return);
Hàm pthread_join() khiến cho thread gọi hàm phải tạm ngưng
thực thi, đợi cho đến khi thread có chỉ số thread ID th kết thúc.
Tham số thread_return chứa kết quả trả về (chính là giá trị của
lệnh return hoặc hàm pthread_exit(…))
Nếu thread kia đã kết thúc trước lời gọi hàm -> lỗi (nonzero)
Nếu có nhiều thread cùng gọi join đến một thread thì cuối cùng
chỉ có một thread (?) được báo kết quả chính xác !!!
3.13
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ pthread_join()
File thr2.c
1. #include
2. #include
3. void* func(void* arg)
4. {
5. int i;
6. for (i = 0; i < 2; i++) {
7. printf ("This is thread %d\n", *((int*)arg));
8. sleep (1);
9. }
10. }
11. int main (int argc, char **argv) {
12. int i;
13. pthread_t tid[3];
14. for (i = 0; i < 3; i++){
15. pthread_create (&tid[i], NULL, func, (void*)&tid[i]);
16. pthread_join (tid[i], NULL);
17. }
18. return 0;
19. }
3.14
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Truyền dữ liệu cho thread
#include
#include
struct char_print_parms {
char character;
int count;
};
void* char_print (void* args) {
struct char_print_parms* p = (struct char_print_parms*) args;
int i;
for (i = 0; i count; ++i)
printf ("%c", p->character);
return NULL;
}
int main () {
pthread_t tid;
struct char_print_parms th_args;
th_args.character = 'X';
th_args.count = 300;
pthread_create (&tid, NULL, &char_print, &th_args);
pthread_join (tid, NULL);
return 0;
}
3.15
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Giới thiệu về IPC
Mục tiêu của IPC
z Cho phép phối hợp hoạt động giữa các quá trình
trong hệ thống
z Giải quyết đụng độ trên vùng tranh chấp
z Truyền thông điệp từ quá trình này đến các quá
trình khác
z Chia sẻ thông tin giữa các quá trình với nhau
3.16
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Giao tiếp và đồng bộ
Synchronization
z Giải quyết tranh chấp
z Đảm bảo thứ tự xử lý
z Các cơ chế:
Lock files
Semaphores
Mutex (pthread)
Communication
z Truyền dữ liệu
z Chia sẻ thông tin
z Các cơ chế:
Signal
Pipes
Message queues
Shared memory
Sockets
RPC/RMI
3.17
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Signals
Dựa vào các sự kiện bất đồng bộ.
Kernel có nhiệm vụ gửi (deliver) sự kiện đến process
Các process có thể tự thiết lập các hành vi ứng xử
tương ứng với sự kiện nhận được.
Signals
(events)
Process
3.18
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Một số signals thường gặp
SIGKILL
SIGSTOP
SIGHUP
SIGPIPE
SIGINT
SIGQUIT
…
Tham khảo thêm dùng các lệnh sau
$ man signal hoặc info signal
$ kill -l
$ more /usr/include/bits/signum.h
3.19
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hành vi của process đối với một sự kiện
Các hành vi có thể thực hiện khi có sự kiện
z Thực hiện các hành vi mặc định (do hệ điều hành qui định)
TERMINATED/ABORT - kết thúc
CORE (Dump) - tạo ra core image (memory dump) và
thoát
STOP - Trì hoãn thực thi
z IGNORE - Bỏ qua signal (ngoại trừ SIGKILL, SIGSTOP)
z CATCH - Thực hiện hành vi do người lập trình định nghĩa
(signal handler).
3.20
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Các nguồn tạo signal
Từ kernel
z Khi xảy ra một số điều kiện về phần cứng (SIGSEGV, SIGFPE)
z Khi xảy ra điều kiện phần mềm (SIGIO)
Từ user
z Tổ hợp phím: Ctrl + C, Ctrl+Z, Ctrl + \
z Khi user dùng lệnh kill
Từ một process thực hiện system call kill():
#include
#include
int kill(pid_t pid, int sig);
Từ lời gọi system call alarm() → tạo ra SIGALARM
3.21
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình với signal
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
int sighold(int sig);
int sigrelse(int sig);
int sigignore(int sig);
int sigpause(int sig);
3.22
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lập trình với signal (t.t)
sighandler_t signal(int signum, sighandler_t handler);
Thay đổi hành vi của process đối với signal
Tham số của hàm signal()
z signum: là số hiệu signal mà bạn muốn thay đổi hành vi
(trừ SIGKILL hay SIGSTOP) - dạng số hay symbolic
z handler: hành vi mới đối với signal, các giá trị có thể là:
SIG_DFL: thiết lập lại hành vi về mặc định (default)
SIG_IGN: lờ đi (ignore) signal tương ứng
Tham chiếu đến hàm xử lý sự kiện (signal-handler) mới
do người dùng tự định nghĩa
3.23
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ lập trình với signal
Bỏ qua signal (sig1.c):
#include
#include
#include
#include
int main() {
int i=0;
if (signal(SIGINT, SIG_IGN) == SIG_ERR)
{
perror("\nSIGINT");
exit(3);
}
while (1);
return 0;
}
Lưu ý: SIGINT tạo ra khi user nhấn Ctrl+C để kết thúc process đang thực thi
Dịch và thực thi:
$ gcc sig1.c –o sig1
$./sig1
^C
^C
^C
3.24
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ lập trình với signal (t.t)
Định nghĩa hành vi mới đối với tín hiệu SIGINT (sig2.c):
#include
#include
#include
#include
void newhandler(int sig) {
printf("\nI received signal %d", sig);
}
int main() {
int i=0;
if (signal(SIGINT, newhandler) == SIG_ERR) {
perror("\nSIGINT");
exit(3);
}
while (1);
return 0;
}
Dịch và thực thi
$ gcc sig2.c -o sig2
$ ./sig2
^C
I received signal 2
^C
I received signal 2
^C
I received signal 2
3.25
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Giao tiếp thông qua PIPE
Là kênh truyền dữ liệu giữa các process với nhau theo
dạng FIFO
Writer Reader…
3.26
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Các tác vụ trên pipe
Write:
#include
ssize_t write (int filedes, const void *buf, size_t count)
Read:
#include
ssize_t read (int filedes, const void *buf, size_t count)
3.27
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hai loại pipe
z Unnamed pipe
có ý nghĩa cục bộ
chỉ dành cho các process có quan hệ bố con với nhau
z Named pipe (còn gọi là FIFO)
có ý nghĩa toàn cục
có thể sử dụng cho các process không liên quan bố con
3.28
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Unnamed pipe
Tạo unnamed pipe:
#include
int pipe( int filedes[2]);
Kết quả
z Thành công, kết quả thực thi hàm pipe() là 0, có hai file descriptor
tương ứng sẽ được trả về trong filedes[0], filedes[1]
z Thất bại: hàm pipe() trả về -1, mã lỗi trong biến ngoại errno
3.29
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Unnamed pipe
filedes1[1] Æ filedes1[0]
filedes2[0] Æ filedes2[1]
Process 1 Process 2
Duplex
z Linux: unidirectional/half-duplex, i.e. filedes[0] chỉ được dùng để
đọc còn filedes[1] chỉ được dùng để ghi dữ liệu
z Solaris: full-duplex, i.e. nếu ghi vào filedes[0], thì filedes[1] được
dùng để đọc và ngược lại
3.30
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ về unnamed pipe
#include
#include
#include
#include
int main() {
int fp[2];
char s1[BUFSIZ];
char s2[BUFSIZ];
pipe(fp);
if (fork()==0) {
printf("\nInput:");
fgets(s1, BUFSIZ, stdin);
s1[strlen(s1)]=0;
close(fp[0]);
write(fp[1], s1, strlen(s1)+1);
}
else {
close(fp[1]);
read(fp[0], s2, BUFSIZ);
printf("\nFrom pipe > %s\n", s2);
}
return 0;
}
Dịch, thực thi
$ gcc pipe.c -o pipe
$ ./pipe
Input: I Love Penguin
From pipe> I Love Penguin
$
3.31
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Dùng pipe để tái định hướng
Pipe có thể được dùng để kết nối các lệnh với nhau (do chương
trình shell thực hiện)
z Ví dụ: $ ps -ef | grep a01 | sort
$ ls | more
Đối với chương trình người dùng, có thể dùng một trong hai
system call sau kết hợp với pipe để thực hiện:
z dup()
z dup2()
3.32
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
dup()
#include
int dup(int filedes);
Chức năng: tạo bản sao của descriptor filedes. File descriptor nhỏ nhất
còn chưa sử dụng sẽ là bản sao của filedes.
Kết quả của hàm dup()
z Thành công: file descriptor bản sao
z Lỗi: -1(mã lỗi trong biến ngoại errno)
File descriptor mới có những thuộc tính chung với file ban đầu
z Cùng chỉ đến một file (hay pipe) đang mở
z Chia sẻ cùng một file pointer
z Có cùng một chế độ truy cập (read, write hoặc read/write)
stdin 0
stdout
stderror
1
2
3
4
stdin 0
stdout
stderror
1
2
3
4
available
dup(1);
file pointed by
file descriptor 1
available
3.33
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
dup2()
#include
int dup2(int filedes, int filedes2);
Tương tự dup(), nhưng dup2() cho phép chỉ định file descriptor
đích
z Descriptor filedes2 trỏ đến cùng một file như filedes
stdin 0
stdout
stderror
1
2
3
4
stdin 0
stdout
stderror
1
2
3
4
dup2(1, 4);
file pointed by
file descriptor 0
3.34
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Named pipe
Tương tự như unnamed pipe
Một số tính năng cần chú ý:
z Được ghi nhận trên file system (directory entry, file
permission)
z Có thể dùng với các process có quan hệ bố con
z Có thể tạo ra từ dấu nhắc lệnh shell (bằng lệnh mknod)
3.35
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Tạo unnamed pipe - mknod()
System call:
#include
#include
int mknod(const char *path, mode_t mode, dev_t dev);
Trong đó
z path: đường dẫn đến pipe (trên file system)
z mode: quyền truy cập trên file = S_IFIFO kết hợp với trị khác
z dev: dùng giá trị 0
C/C++ library call
#include
#include
int mkfifo (const char *pathname, mode_t mode);
3.36
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ
#include
#include
#include
#include
#include
extern int errno;
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define PERMS 0666
int main(){
char s1[BUFSIZ], s2[BUFSIZ];
int childpid, readfd, writefd;
Dịch & thực thi
$gcc fifo.c –o fifo
$./fifo
Parent inputs string and write to FIFO1:Test1
Child read from FIFO1:Test1
Input string from child to feedback:Test2
Feedback data from FIFO2:Test2
3.37
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ
if ( (mknod(FIFO1, S_IFIFO | PERMS, 0) < 0) && (errno !=EEXIST)) {
printf("can't create fifo 1: %s", FIFO1);
exit(1);
}
if ( (mknod(FIFO2, S_IFIFO | PERMS, 0) < 0) && (errno !=EEXIST)) {
unlink(FIFO1);
printf("can't create fifo 2: %s", FIFO2);
exit(1);
}
if ( (childpid = fork()) < 0) {
printf("can't fork");
exit(1);
}
3.38
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ
else if (childpid > 0) { /* parent */
if ((writefd = open(FIFO1, 1)) < 0) perror("parent: can't open write fifo");
if ((readfd = open(FIFO2, 0)) < 0)perror("parent: can't open read fifo");
printf("\nParent inputs string and write to FIFO1:");
gets(s1); s1[strlen(s1)]=0;
write(writefd, s1, strlen(s1)+1);
read(readfd, s2, BUFSIZ);
printf("\nFeedback data from FIFO2:%s\n",s2);
while (wait((int *) 0) != childpid); /* wait for child finish */
close(readfd);
close(writefd);
if (unlink(FIFO1) < 0) perror(“Can't unlink FIFO1”);
if (unlink(FIFO2) < 0) perror(“Can't unlink FIFO2”);
exit(0);
}
3.39
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Ví dụ
else { /* child */
if ( (readfd = open(FIFO1, 0)) < 0) perror("child: can't open read fifo");
if ( (writefd = open(FIFO2, 1)) < 0) perror("child: can't open write fifo");
read(readfd, s2, BUFSIZ);
printf("\nChild read from FIFO1:%s\n",s2);
printf("\nInput string from child to feedback:");
gets(s1); s1[strlen(s1)]=0;
write(writefd, s1, strlen(s1)+1);
close(readfd);
close(writefd);
exit(0);
}
}
3.40
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
SystemV IPC
Gồm: message queue, shared memory, semaphore
Có một số thuộc tính chung như
z Người tạo, người sở hữu (owner), quyền truy cập (perms)
Có thể theo dõi trạng thái các IPC bằng lệnh ipcs
$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
3.41
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Lệnh IPC trong Linux
Theo dõi trạng thái các IPC (gồm message queue, semaphore,
shared memory)
z ipcs hoặc ipcs -a
Theo dõi trạng thái các semaphore của hệ thống
z ipcs -s
Theo dõi trạng thái các vùng nhớ chia sẻ của hệ thống
z ipcs -m
Loại bỏ một semaphore (phải đủ quyền hạn)
z ipcrm sem sem_id hoặc ipcs -s sem_id
Loại bỏ một vùng nhớ chia sẻ (phải đủ quyền hạn)
z ipcrm shm shm_id hoặc ipcs -shm shm_id
3.42
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Các thao tác chủ yếu trên đối tượng IPC
Tác vụ get
z tạo các đối tượng IPC. Ví dụ
semget(), shmget()
Tác vụ điều khiển:
z lấy hoặc thay đổi thuộc tính của các đối tượng IPC
semctl(), shmctl()
Specific operations
z thay đổi trạng thái hay nội dung của đối tượng IPC nhằm
tương tác với quá trình khác. Ví dụ
semop()
shmat(), shmdt()
3.43
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Semaphore
Đồng bộ các process theo giải thuật của semaphore
Biến semaphore
z số nguyên, truy cập qua các hàm do hệ điều hành cung cấp:
P (wait), V (signal)
Đảm bảo loại trừ tương hỗ
Trong UNIX System V, semaphore được dùng theo
set – danh sách các semaphore.
3.44
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hàm semget()
Tạo semaphore:
key: giá trị key cho IPC object, nếu key = IPC_PRIVATE thì
semaphore tạo ra chỉ được sử dụng trong nội bộ process.
nsems: số lượng semaphore trong semaphore set, thông thường
chỉ cần dùng 1 semaphore.
semflag: IPC_CREAT, IPC_EXCL và có thể OR với giá trị ấn định
quyền truy cập (tương tự quyền hạn trên một file).
Ví dụ là:
sset1_id = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600);
sset2_id = semget(12345, 1, IPC_CREAT | IPC_EXCL | 0666);
3.45
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Tạo key cho IPC object
Mỗi IPC object (là một khối shared memory hoặc một
semaphore) được xác định bởi số danh định gọi là key.
z Key kiểu là key_t
Process truy cập một IPC_object thông qua key của đối tượng
đó.
Cách tạo một IPC key dùng hàm ftok()
⇒ các process khác nhau chỉ cần cung cấp path và id giống nhau
là có thể tạo đúng key truy cập đến cùng một IPC object.
3.46
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hàm semop()
Thực hiện các thao tác trên semaphore
semid : semaphore set ID do hàm semget() trả về
nsops : số semaphores trong semaphore cần thao tác
sops : là danh sách gồm nsops cấu trúc sembuf định ra
các thao tác cho từng semaphore trong tập semaphore.
3.47
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hàm semop()
Cấu trúc sembuf
struct sembuf {
ushort sem_num; /*semaphore #*/
short sem_op; /*operation*/
short sem_flg; /*operation flags*/ }
sem_num : chỉ số của semaphore trong semaphore set,
chỉ số này bắt đầu từ 0
sem_op : là số nguyên,
>0: tăng giá trị semaphore
<0: giảm giá trị semaphore
sem_flg : IPC_NOWAIT: non-blocking mode
SEM_UNDO: undo operation
3.48
Khoa Công nghệ Thông tin - Đại học Bách Khoa Tp. HCM
Hành vi