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?
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 ...
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.
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
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
Basé sur la réponse de Kyle, ici est un tutoriel rapide montrant comment faire exactement cela.
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"
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 ); }