哈工大 作業系統 lab4 訊號量的實現和應用解答
阿新 • • 發佈:2022-04-19
所需資料結構(定義在標頭檔案中,使用者也需要知道):
#define SEM_FAILED (void*) 0 #define SEM_NAME_MAX_LEN 16 #define SEM_QUEUE_LEN 16 struct semaphore_queue { int front; int rear; struct task_struct* wait_tasks[SEM_QUEUE_LEN]; }; typedef struct semaphore_queue sem_queue; struct semaphore_t { int val; int open_flag; char name[SEM_NAME_MAX_LEN]; sem_queue wait_queue; }; typedef struct semaphore_t sem_t;
對上述資料結構的一些基本操作(實現了一個迴圈佇列):
#define __LIBRARY__ #include <unistd.h> /* type def */ #include <linux/sched.h> /* schedule */ #include <linux/kernel.h> /* printk */ #include <asm/segment.h> /* get_fs_byte */ #include <asm/system.h> /* sti cli */ #define SEM_COUNT 32 sem_t semaphores[SEM_COUNT]; void init_queue(sem_queue* q) { q->front = q->rear = 0; } int empty(sem_queue* q) { return q->front == q->rear ? 1 : 0; } int full(sem_queue* q) { return (q->rear + 1) % SEM_QUEUE_LEN == q->front ? 1 : 0; } struct task_struct* front(sem_queue* q) { if(empty(q)) { printk("front fail! no task in queue\n"); return NULL; } struct task_struct *tmp = q->wait_tasks[q->front]; return tmp; } void pop(sem_queue* q) { if (empty(q)) { printk("pop fail! no task in queue!\n"); return; } q->front = (q->front + 1) % SEM_QUEUE_LEN; } void push(sem_queue* q, struct task_struct* p) { if (full(q)) { printk("push fail! queue is full!\n"); return; } q->wait_tasks[q->rear] = p; q->rear = (q->rear + 1) % SEM_QUEUE_LEN; } int sem_exit(const char* name) { int i = 0; for (i = 0; i < SEM_COUNT; ++i) { if (semaphores[i].open_flag == 1 && strcmp(name, semaphores[i].name) == 0) { return i; } } return -1; }
sem_open
實現:
sem_t* sys_sem_open(const char* name, unsigned int value) { char buffer[SEM_NAME_MAX_LEN]; int i = 0; for (i = 0; i < SEM_NAME_MAX_LEN; ++i) { buffer[i] = get_fs_byte(name + i); if (buffer[i] == '\0') { break; } } if (i >= SEM_NAME_MAX_LEN) { printk("name too long!\n"); return NULL; } int idx = sem_exit(buffer); if (idx != -1) { // exits return &semaphores[idx]; } // not exits for (i = 0; i < SEM_COUNT; ++i) { if (semaphores[i].open_flag == 0) { strcpy(semaphores[i].name, buffer); semaphores[i].open_flag = 1; semaphores[i].val = value; init_queue(&(semaphores[i].wait_queue)); return &semaphores[i]; } } // can't find a slot printk("MAX SEMAPHORE's NUMBER IS %d, NOW FULL!\n", SEM_COUNT); return NULL; }
sem_unlink
實現:
int sys_sem_unlink(const char *name) {
char buffer[SEM_NAME_MAX_LEN];
int i = 0;
for (i = 0; i < SEM_NAME_MAX_LEN; ++i) {
buffer[i] = get_fs_byte(name + i);
if (buffer[i] == '\0') {
break;
}
}
if (i >= SEM_NAME_MAX_LEN) {
printk("name too long!\n");
return -1;
}
int idx = sem_exit(buffer);
if (idx == -1) { // not exits
printk("SEM %s NOT EXIT\n", buffer);
return -1;
}
semaphores[idx].val = 0;
semaphores[idx].open_flag = 0;
strcpy(semaphores[idx].name, "\0");
return 0;
}
sem_wait
實現:
int sys_sem_wait(sem_t* sem) {
if (sem == NULL) {
return -1;
}
cli();
if (--sem->val < 0) {
current->state = TASK_UNINTERRUPTIBLE;
push(&(sem->wait_queue), current);
schedule();
}
sti();
return 0;
}
sem_wait
實現:
int sys_sem_post(sem_t* sem) {
if (sem == NULL) {
return -1;
}
cli();
if (++sem->val <= 0) {
struct task_struct* p = front(&(sem->wait_queue));
if (p != NULL) {
pop(&(sem->wait_queue));
p->state = TASK_RUNNING;
}
}
sti();
return 0;
}
然後按新增系統呼叫的流程新增上系統呼叫即可。
有一個比較坑的地方是,新增的系統呼叫可能沒用,編譯不過去(拷貝個unistd.h
到linux0.11即可)。