Я упираюсь в стену с проектом, над которым работаю, и мне было интересно, может ли кто-нибудь оказать мне некоторую помощь. Я постараюсь упростить свой код, чтобы вы не смотрели на 100+ строк треп. Я почти уверен, что важен только первый блок кода, остальные - это мои системные вызовы в sys.c для справки.
Я должен создать программу, имитирующую реализацию синхронизации процессов с приоритетом читателя, используя мои собственные семафоры. Когда я запускаю его, я захожу в тупик всякий раз, когда читатель переходит к критическому разделу. Не знаю, что я сделал не так.
Пример вывода:
Writer 0 написал- 6
писатель 1 написал - 4
Писатель 2 написал - 2
Читатель 0 прочитал- 2
а потом зависает.
Насколько я могу судить, семафор критической секции никогда не будет выпущен.
Я считаю, что проблема связана с моей программой, а не с моим семафором и операциями ожидания и сигнала, но я включил их ниже для справки.
Заранее спасибо.
Моя попытка такова: я не учел свою инициализацию и отображение памяти, это базовая структура.
Примечания: RWwait и RWsignal - это методы-оболочки, которые успешно выполняют системные вызовы моих операций с семафором. csMutex предназначен для управления доступом к критическому разделу. nrMutex предназначен для управления очередью читателей в критическую секцию. Оба значения мьютекса изначально равны 1. * число - это указатель на число, к которому и читатели, и писатели имеют доступ.
int i;
//create writers
for(i=0; i < writers; i++){
if (fork()==0){
while(1){
RWwait(csMutex); //wait for the critical section and lock
*number = rand() % 10;
printf("Writer %d wrote- %d\n", i, *number);
RWsignal(csMutex);//unlock critical section
}
}
}
int nr = 0; //number of readers
//create readers
for(i=0; i < readers; i++){
if (fork()==0){
while(1){
RWwait(nrMutex);
nr++;
if (nr == 1)
RWwait(csMutex);
RWsignal(nrMutex);
printf("Reader %d read- %d\n", i, *number);
RWwait(nrMutex);
nr--;
if (nr == 0)
RWsignal(csMutex);
RWsignal(nrMutex);
}
}
}
ЭТО МОИ СИСТЕМНЫЕ ВЫЗОВЫ И СТРУКТУРЫ В sys.c ОПЯТЬ, ТОЛЬКО ДЛЯ СПРАВКИ
struct ProcQ {
struct task_struct *ts;
struct ProcQ *next;
};
и
struct RW_Sem {
int value;
char *type;
//Front and back nodes for the queue
struct ProcQ *front;
struct ProcQ *back;
};
Подождите, операция:
asmlinkage long sys_RW_wait(struct RW_Sem *sem){
spin_lock(&sem_lock); //locks the program
sem->value -= 1; //decrement value
if (sem->value < 0){ //insert into queue
struct ProcQ *node; //create a new node for the queue
node = (struct ProcQ*)kmalloc(sizeof(struct ProcQ), GFP_KERNEL);
node->ts = current; //assign this process to task_struct
node->next = NULL; //assign the next node to null
if(sem->front == NULL){ //if the process queue is empty
sem->front = node;
sem->back = node;
}
else{ //if the queue is NOT empty
sem->back->next = node;
sem->back = node;
}
set_current_state(TASK_INTERRUPTIBLE); //sleep my child
spin_unlock(&sem_lock); //unlock
schedule();
}
else{ //queue bypass
spin_unlock(&sem_lock);
}
return 0;
}
Сигнальная операция:
asmlinkage long sys_RW_signal(struct RW_Sem *sem){
spin_lock(&sem_lock); //locks the program
sem->value += 1; //increment value
if(sem->value <= 0){ //wake up process, otherwise bypass
struct ProcQ *dqProc; //temporary node pointer for signaled process
struct task_struct *wake; //temp for task struct to wake
dqProc = sem->front;
if (dqProc != NULL) {
wake = dqProc->ts;
if(sem->front==sem->back){ //if only item in queue
sem->front = NULL;
sem->back = NULL;
}
else{
sem->front = dqProc->next;
}
wake_up_process(wake); //wake up!
kfree(dqProc); //free that space
}
}
spin_unlock(&sem_lock); //unlock
return 0; //success!
}