2009-11-12 4 views
0

Je fais un cours sur les systèmes d'exploitation et nous travaillons sous Linux Red Hat 8.0 Dans le cadre d'une mission, j'ai dû changer sys close et sys open. Les modifications apportées à sys close sont passées sans incident, mais lorsque j'introduis les changements de sys, le système d'exploitation rencontre une erreur lors du démarrage, affirmant qu'il ne peut pas monter la racine fs, et invoque la panique. EIP est apparemment à proximité de sys lorsque cela se produit.Panique du noyau après les changements dans sys_close

Voici les changements que j'ai fait (chercher les « ajouts » HW1 commentaire): Dans fs/open.c:

asmlinkage long sys_open(const char * filename, int flags, int mode) 
{ 
    char * tmp; 
    int fd, error; 
    event_t* new_event; 

#if BITS_PER_LONG != 32 
    flags |= O_LARGEFILE; 
#endif 
    tmp = getname(filename); 
    fd = PTR_ERR(tmp); 
    if (!IS_ERR(tmp)) { 
     fd = get_unused_fd(); 
     if (fd >= 0) { 
      struct file *f = filp_open(tmp, flags, mode); 
      error = PTR_ERR(f); 
      if (IS_ERR(f)) 
       goto out_error; 
      fd_install(fd, f); 
     } 
     /* HW1 additions */ 
     if (current->record_flag==1){ 
      new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL); 
      if (!new_event){ 
       new_event->type=Open; 
       strcpy(new_event->filename, tmp); 
       file_queue_add(*new_event, current->queue); 
      } 
     } 
     /* End HW1 additions */ 
out: 
     putname(tmp); 
    } 
    return fd; 

out_error: 
    put_unused_fd(fd); 
    fd = error; 
    goto out; 
} 

asmlinkage long sys_close(unsigned int fd) 
{ 
    struct file * filp; 
    struct files_struct *files = current->files; 
    event_t* new_event; 
    char* tmp = files->fd[fd]->f_dentry->d_name.name; 

    write_lock(&files->file_lock); 
    if (fd >= files->max_fds) 
     goto out_unlock; 
    filp = files->fd[fd]; 
    if (!filp) 
     goto out_unlock; 
    files->fd[fd] = NULL; 
    FD_CLR(fd, files->close_on_exec); 
    __put_unused_fd(files, fd); 
    write_unlock(&files->file_lock); 
    /* HW1 additions */  
    if(current->record_flag == 1){ 
     new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL); 
     if (!new_event){ 
      new_event->type=Close; 
      strcpy(new_event->filename, tmp); 
      file_queue_add(*new_event, current->queue); 
     } 
    } 
    /* End HW1 additions */ 
    return filp_close(filp, files); 

out_unlock: 
    write_unlock(&files->file_lock); 
    return -EBADF; 
} 

Le task_struct défini dans schedule.h a été modifiée à la fin d'inclure :

unsigned int record_flag; /* when zero: do not record. when one: record. */ 
file_queue* queue; 

et file d'attente de fichiers ainsi que l'événement t sont définis dans un fichier séparé comme suit:

typedef enum {Open, Close} EventType; 

typedef struct event_t{ 
    EventType type; 
    char filename[256]; 
}event_t; 

typedef struct file_quque_t{ 
    event_t queue[101]; 
    int head, tail; 
}file_queue; 

file d'attente de fichiers ajouter fonctionne comme ceci:

void file_queue_add(event_t event, file_queue* queue){ 
    queue->queue[queue->head]=event; 
    queue->head = (queue->head+1) % 101; 
    if (queue->head==queue->tail){ 
     queue->tail=(queue->tail+1) % 101; 
    } 
} 
+0

Pouvez-vous mettre une pile de vidage lorsque le système panique? –

Répondre

2
if (!new_event) { 
    new_event->type = … 

C'est équivalent à if (new_event == NULL). Je pense que vous voulez dire if (new_event != NULL), que les gens du noyau écrivent généralement comme if (new_event).

+0

Vous avez raison, mais cela ne résout pas le problème. Ce qui m'embarrasse vraiment, c'est que puisque tous les processus sont créés pour que record_flag soit mis à 0, cette partie de code ne devrait même pas avoir d'effet, et pourtant le problème ne se produit qu'après avoir introduit ces changements. –

0

Pouvez-vous s'il vous plaît publier le stackdump de l'erreur. Je ne vois pas d'endroit où la structure queue_info est allouée de la mémoire. Une dernière chose est que vous ne pouvez pas être sûr que le processus record_flag sera toujours zéro s'il n'est pas affecté au noyau, car le noyau est un programme qui fonctionne depuis longtemps et la mémoire contient des ordures.

Il est également possible de vérifier l'emplacement exact de la fonction en regardant la trace de la pile.

Questions connexes