owned this note
owned this note
Published
Linked with GitHub
# Linux operating system project 2
###### tags: `linux OS`
## Description
* 在kernel中define 3個wait queue : project2_queue_1、project2_queue_2、project2_queue_3
* 新增兩個system call
1. int enter_wait_queue(int x),
* process can use it to sleep in project2_queue_x, where x is equal to 1 or 2 or 3
2. int clean_wait_queue(int x)
* process can use it to wake up **all** sleeping processes in project2_queue_x where x is equal to 1 or 2 or 3.
## user program
* enter_queue.c : 用來檢驗enter_wait_queue()
```c=
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define _GNU_SOURCE
#define gettid() syscall(SYS_gettid)
void main()
{
int random_num;
int ttid, count;
char str[300];
FILE *fp;
struct timeval t1, t2;
gettimeofday(&t1, NULL);
ttid=gettid();
count=0;
/*open a file for writing. The filename consist of the following two substrings,
"file_" and the string converting from the result of gettid(). Hence, if the result of gettid is 123,
the file name is file_123. We use file_gettid to call this file in the following pseudo code. */
char filename[30];
sprintf(filename, "file_%d.txt\n", ttid);
for(;;)
{
gettimeofday(&t2, NULL);
/*If the time difference between t2 and t1 is greater than 3 minutes, break;*/
int timediff=t2.tv_sec-t1.tv_sec;
if (timediff>=180)break;
random_num= (rand()%3)+1;
count++;
sprintf(str, "process %d is added into wait queue project2_queue_%d the %d th time at time ...\n", ttid, random_num, count);
/*write the string stored in array str[] into file file_gettid.*/
printf("%d\n",random_num);
fp = fopen(filename, "w");
fprintf(fp,str);
fclose(fp);
int a= syscall(359,random_num);
printf("%d\n",a);
}
printf("process %d completes!\n", ttid);
}
```
* wait_queue.c : 336
```c=
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/list.h>
DECLARE_WAIT_QUEUE_HEAD(project2_queue_1);
DECLARE_WAIT_QUEUE_HEAD(project2_queue_2);
DECLARE_WAIT_QUEUE_HEAD(project2_queue_3);
asmlinkage int enter_wait_queue(int x) {
DEFINE_WAIT(p);
if (x==1){
printk("project2_queue_1\n");
prepare_to_wait(&project2_queue_1,&p,TASK_INTERRUPTIBLE);
printk("project2_queue_1 schedule\n");
schedule();
printk("project2_queue_1 exit.\n");
return 1;
}
else if (x==2){
printk("project2_queue_2\n");
prepare_to_wait(&project2_queue_2,&p,TASK_INTERRUPTIBLE);
printk("project2_queue_2 schedule\n");
schedule();
printk("project2_queue_2 exit.\n");
return 1;
}
else {
printk("project2_queue_3\n");
prepare_to_wait(&project2_queue_3,&p,TASK_INTERRUPTIBLE);
printk("project2_queue_3 schedule\n");
schedule();
printk("project2_queue_3 exit.\n");
return 1;
}
return 0;
}
asmlinkage int clean_wait_queue(int x) {
if (x==1){
printk("wake up Q1 \n");
wake_up_all(&project2_queue_1);
return 1;
}
else if (x==2){
printk("wake up Q2 \n");
wake_up_all(&project2_queue_2);
return 1;
}
else {
printk("wake up Q3 \n");
wake_up_all(&project2_queue_3);
return 1;
}
return 0;
}
```
* clear_queue.c : 用來檢驗clear_wait_queue()
```c=
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <syscall.h>
#include <time.h>
#define _GNU_SOURCE
#define gettid() syscall(SYS_gettid)
void main()
{
int random_num1,random_num2;
int ttid,count;
char str[300];
struct timeval t1, t2;
FILE *fp;
gettimeofday(&t1, NULL);
ttid=gettid();
count=0;
srand(time(NULL));
/*open a file for writing. The filename consist of the following two substrings,
"file_" and the string converting from the result of gettid(). Hence, if the result of gettid is 123,
the file name is file_123. We use file_gettid to call this file in the following pseudo code. */
char filename[20];
sprintf(filename, "file_%d.txt\n", ttid);
while(1)
{
gettimeofday(&t2, NULL);
/*If the time difference between t2 and t1 is greater than 5 minutes, break;*/
int timediff=t2.tv_sec-t1.tv_sec;
if (timediff>=15)break;
random_num1= (rand()%3)+1;
random_num2= (rand()%10);
sleep(random_num2);
sprintf(str, "Wake up all processes in wait queue project2_queue_%d at time ...\n", 1);
/*write the string stored in array str[] into file file_gettid;*/
fp = fopen(filename, "w");
fprintf(fp, str);
fclose(fp);
syscall(360, random_num1);
printf("Done Q%d\n", random_num1);
}
/*write the string "Clean wait wait queue project2_queue_1" into file file_gettid;*/
syscall(360, 1);
str[100]="Clean wait wait queue project2_queue_1";
fp = fopen(filename, "w");
fprintf(fp, str);
fclose(fp);
//write the string "Clean wait wait queue project2_queue_2" into file file_gettid;
syscall(360, 2);
str[100]="Clean wait wait queue project2_queue_2";
fp = fopen(filename, "w");
fprintf(fp, str);
fclose(fp);
//write the string "Clean wait wait queue project2_queue_3" into file file_gettid;
syscall(360, 3);
str[100]="Clean wait wait queue project2_queue_3";
fp = fopen(filename, "w");
fprintf(fp, str);
fclose(fp);
//close file file_gettid;
printf("process %d completes!\n", ttid);
}
```
## method
wait_queue 提供4個 function 可以使用,兩個是用來將 process 加到 wait_queue 的:
* sleep_on( struct wait_queue **wq );
* interruptible_sleep_on( struct wait_queue **wq );
另外兩個則是將process從wait_queue上叫醒的。
* wake_up( struct wait_queue **wq );
* wake_up_interruptible( struct wait_queue **wq );
如果是用 interruptible_sleep_on() 來將 process 放到 wait_queue 時,如果有人送一個 signal 給這個 process,那它就會自動從 wait_queue 中醒來。
但是如果你是用 sleep_on() 把 process 放到 wq 中的話,那不管你送任何的 signal 給它,它還是不會理你的。除非你是使用 wake_up() 將它叫醒。
sleep 有兩組。wake_up 也有兩組。wake_up_interruptible() 會將 wq 中使用 interruptible_sleep_on() 的 process 叫醒。
至於 wake_up() 則是會將 wq 中所有的 process 叫醒。包括使用 interruptible_sleep_on() 的 process。**所以根據project要求,我們應該用wake_up()**
[wake up 家族funciton](https://blog.csdn.net/myxmu/article/details/7973990)
[wait queue的使用](https://blog.csdn.net/u012218309/article/details/81148083?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-7.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-7.control)
## error message
error: ‘project2_queue_1’ undeclared