Envoi du message Netlink Taskstats à l’aide de libnl-3

Je veux lire les statistiques du kernel Linux d’un seul thread en utilisant netlink socket et taskstats.

Je pouvais faire en sorte que taskstats fonctionne avec un wrapper python ( https://github.com/facebook/gnlpy ) mais je veux faire une implémentation en C.

Après avoir configuré le socket, les parameters du message et l’envoi, le destinataire

nl_recvmsgs_default(sock) 

renvoie toujours un code d’erreur -7 (“données d’entrée ou paramètre non valide”) ou -12 (“object introuvable”), en fonction de la manière dont je crée le message à envoyer.

J’ai vérifié toutes les invocations de méthodes avant nl_recvmsgs_default (sock) mais je ne reçois aucune erreur. J’imagine qu’il me manque une partie dans la configuration du message ou de la socket, mais je ne sais pas de quelle partie il s’agit.

 #include  #include  #include  #include  #include  #include  int callback_message(struct nl_msg *, void *); int main(int argc, char ** argv) { struct nl_sock * sock; struct nl_msg * msg; int family; sock = nl_socket_alloc(); // Connect to generic netlink socket on kernel side genl_connect(sock); // get the id for the TASKSTATS generic family family = genl_ctrl_resolve(sock, "TASKSTATS"); // Allocate a new netlink message and inherit netlink message header. msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) //error code: -7 NLE_INVAL "Invalid input data or parameter", nla_put_ssortingng(msg, TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, "0"); //error code: -12 NLE_OBJ_NOTFOUND "Obj not found" //nla_put_ssortingng(msg, TASKSTATS_CMD_ATTR_PID, "583"); nl_send_auto(sock, msg); nlmsg_free(msg); // specify a callback for inbound messages nl_socket_modify_cb(sock, NL_CB_MSG_IN, NL_CB_CUSTOM, callback_message, NULL); // gives error code -7 or -12 depending on the two nla_put_ssortingng alternatives above printf("recv code (0 = success): %d", nl_recvmsgs_default(sock)); } int callback_message(struct nl_msg * nlmsg, void * arg) { struct nlmsghdr * nlhdr; struct nlattr * nlattrs[TASKSTATS_TYPE_MAX + 1]; struct nlattr * nlattr; struct taskstats * stats; int rem; nlhdr = nlmsg_hdr(nlmsg); int answer; if ((answer = genlmsg_parse(nlhdr, 0, nlattrs, TASKSTATS_TYPE_MAX, NULL)) ac_pid); printf("command: %s\n", stats->ac_comm); printf("status: %u\n", stats->ac_exitcode); printf("time:\n"); printf(" start: %u\n", stats->ac_btime); printf(" elapsed: %llu\n", stats->ac_etime); printf(" user: %llu\n", stats->ac_utime); printf(" system: %llu\n", stats->ac_stime); printf("memory:\n"); printf(" bytetime:\n"); printf(" rss: %llu\n", stats->coremem); printf(" vsz: %llu\n", stats->virtmem); printf(" peak:\n"); printf(" rss: %llu\n", stats->hiwater_rss); printf(" vsz: %llu\n", stats->hiwater_vm); printf("io:\n"); printf(" bytes:\n"); printf(" read: %llu\n", stats->read_char); printf(" write: %llu\n", stats->write_char); printf(" syscalls:\n"); printf(" read: %llu\n", stats->read_syscalls); printf(" write: %llu\n", stats->write_syscalls); } else { printf("unknown atsortingbute format received\n"); } return 0; } 

Le code que vous avez fourni fonctionne bien pour moi, à l’exception d’une erreur de syntaxe à la ligne 26. Assurez-vous que vous exécutez le programme en tant que root. Notez que vous créez un écouteur pour les tâches existantes, mais que vous lisez un seul message, qui est, pour autant que je sache, un ACK. La lecture du socket dans une boucle while (1) affiche les messages analysés chaque fois qu’une tâche se termine sur la CPU 0.

EDIT: Si vous obtenez des statistiques pour un seul PID, vous devriez utiliser nla_put_u32 à la place:

 nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, 583); 

où 583 est un identifiant de processus existant.