web-dev-qa-db-fra.com

Comment ajouter un message qui sera lu avec dmesg?

J'essaie d'écrire des messages personnalisés dans ma sortie dmesg. J'ai essayé:

logger "Hello"

mais cela ne fonctionne pas. Il se termine sans erreur, mais aucun "Bonjour" n'apparaît dans la sortie de:

dmesg

J'utilise un Fedora 9, et il semble qu'il n'y ait pas de démon syslogd/klogd en cours d'exécution. Cependant, tous mes messages du noyau sont écrits avec succès dans le tampon dmesg.

Une idée?

45
calandoa

dmesg affiche ce qui se trouve dans le tampon du noyau, tandis que logger est pour syslogd. Je pense que si vous voulez imprimer des choses dans le tampon du noyau, vous devrez créer un pilote qui utilise la fonction du noyau printk(). Si vous le voulez juste dans /var/log/messages, Alors avec une configuration "normale", je pense que ce que vous avez fait avec logger est déjà très bien.

L'exemple le plus élémentaire d'un pilote avec printk() serait:

bonjour c:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
    printk(KERN_INFO "Hello world\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye world\n");

}

Makefile:

obj-m += hello.o

all:
    make -C /lib/modules/$(Shell uname -r)/build M=$(PWD) modules

Alors:

$ make
$ Sudo insmod hello.ko
$ dmesg | tail -n1
 [7089996.746366] Hello world

http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121 pour plus ...

37
Kyle Brandt

Vous pouvez, en tant que root, écrire à /dev/kmsg pour imprimer dans le tampon de messages du noyau:

 fixnum:~# echo Some message > /dev/kmsg
 fixnum:~# dmesg | tail -n1
 [28078118.692242] Some message

J'ai testé cela sur mon serveur et un périphérique Linux intégré, et cela fonctionne sur les deux, donc je vais juste supposer que cela fonctionne à peu près partout.

114
wvdschel

Basé sur le module de Kyle ci-dessus:


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static int pk_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
        char string[256];
        count = count < 255 ? count : 255;

        if(copy_from_user(string, buffer, count))
                return -EFAULT;

        string[count] = '\0';        
        printk(string);
        return count;
}


static int __init printk_init(void)
{
        struct proc_dir_entry *pk_file;

        pk_file = create_proc_entry("printk", 0222, NULL);
        if(pk_file == NULL)
                return -ENOMEM;

        pk_file->write_proc = pk_write;
        pk_file->owner = THIS_MODULE;

        return 0;
}

static void __exit printk_cleanup(void)
{
        remove_proc_entry("printk", NULL);
}

module_init(printk_init);
module_exit(printk_cleanup);
MODULE_LICENSE("GPL");

Pour faire un printk depuis l'espace utilisateur:

echo "Hello" > /proc/printk
13
calandoa

La réponse de @ Calandoa ne fonctionne plus pour le noyau +3.10. Combiné son code et l'exemple de code que j'ai trouvé ici . Puis amélioré la qualité du code ...

Code enregistré dans printk_user.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static ssize_t write_proc(struct file *filep, const char *buffer, size_t count, loff_t *offsetp)
{
    char string[256];
    count = count < 255 ? count : 255;

    if(copy_from_user(string, buffer, count) != 0) {
        return -EFAULT;
    }

    string[count] = '\0';
    printk(string);
    return count;
}

static const struct file_operations proc_fops = {
    .owner = THIS_MODULE,
    .write = write_proc,
};

static int proc_init(void) {
    struct proc_dir_entry *proc_file;
    proc_file = proc_create("printk_user", 0, NULL, &proc_fops);

    if(proc_file == NULL) {
        return -ENOMEM;
    }

    return 0;
}

static void proc_cleanup(void) {
    remove_proc_entry("printk_user", NULL);
}

MODULE_LICENSE("GPL"); 
module_init(proc_init);
module_exit(proc_cleanup);

Faire en utilisant ce Makefile

TARGET = printk_user
obj-m := $(TARGET).o

KERNEL_VERSION=$(Shell uname -r)
KDIR = /lib/modules/$(KERNEL_VERSION)/build
PWD = $(Shell pwd)

printk:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean
5
kevinf

Basé sur la réponse de Kyle, ici est un tutoriel rapide montrant comment faire exactement cela.

3
TCampbell

Je pensais que j'irais de l'avant et inclurais un exemple complet de quelque chose que les gens peuvent simplement compiler et exécuter pour ceux qui ne sont pas aussi compétents avec C basé sur la réponse de @BuvinJ

#include <stdio.h>
#include <string.h>
#include <fcntl.h> // open function
#include <unistd.h> // close function
#include "sys/syscall.h"


int main(); // Let's not worry about this for now

void dmesg( const char *tag, const char *msg, const int len )
{
    const int TAG_LEN=3;
    char buffer[128]={0};
    memcpy( &buffer[0], tag, TAG_LEN );
    memcpy( &buffer[TAG_LEN], msg, len );
    int fd_kmsg = open( "/dev/kmsg", O_WRONLY );
    write( fd_kmsg, &buffer, TAG_LEN+len );
    close( fd_kmsg );
}
void dmesgWarn(  const char *msg, const int len ){ dmesg( "<4>", msg, len ); }
void dmesgInfo(  const char *msg, const int len ){ dmesg( "<6>", msg, len ); }
void dmesgDebug( const char *msg, const int len ){ dmesg( "<7>", msg, len ); }


int main(int argc, char **argv)
{
    int getmysize = strlen(argv[1]);
    printf("%d\n", getmysize);

    printf("To be written: %s\nSize of argument: %d\n", argv[1], getmysize);
    // dmesgWarn dmesgInfo or dmesgDebug
    dmesgDebug(argv[1], getmysize);
};

Pour exécuter, enregistrez ce qui précède sous kmsg.c et gcc kmsg.c -o kmsg; Sudo ./kmsg "chaîne que vous souhaitez ajouter à/dev/kmsg"

2
linuxgeek

Je voulais juste quelques messages de débogage rapides dans un démon écrit par quelqu'un d'autre dans un noyau compatible. J'ai rencontré une erreur de compilation en essayant d'utiliser printk, comme <linux/module.h> n'a pas pu être inclus. Plutôt que de lutter contre cela de manière excessive (pour le faire de la bonne façon), j'ai triché et utilisé la solution de contournement paresseuse mais fonctionnelle de 5 minutes suivante:

void dmesg( const char *tag, const char *msg, const int len )
{
    const int TAG_LEN=3;
    char buffer[128]={0};
    memcpy( &buffer[0], tag, TAG_LEN );
    memcpy( &buffer[TAG_LEN], msg, len );
    int fd_kmsg = open( "/dev/kmsg", O_WRONLY );
    write( fd_kmsg, &buffer, TAG_LEN+len );
    close( fd_kmsg );
}
void dmesgWarn(  const char *msg, const int len ){ dmesg( "<4>", msg, len ); }
void dmesgInfo(  const char *msg, const int len ){ dmesg( "<6>", msg, len ); }
void dmesgDebug( const char *msg, const int len ){ dmesg( "<7>", msg, len ); }
0
BuvinJ