i want read out linux kernel statistics of single thread using netlink socket , taskstats.
i taskstats work using python wrapper (https://github.com/facebook/gnlpy) want c implementation.
after setting socket, message parameters , sending, receiving
nl_recvmsgs_default(sock)
always returns error code -7 ("invalid input data or parameter") or -12 ("object not found") depending on how create message send.
i checked method invocations before nl_recvmsgs_default(sock) dont error back. guess missing part in setting message or socket, dont know part is.
#include <stdlib.h> #include <unistd.h> #include <linux/taskstats.h> #include <netlink/netlink.h> #include <netlink/genl/genl.h> #include <netlink/genl/ctrl.h> 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 generic netlink socket on kernel side genl_connect(sock); // id taskstats generic family family = genl_ctrl_resolve(sock, "taskstats"); // allocate new netlink message , 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_string(msg, taskstats_cmd_attr_register_cpumask, "0"); //error code: -12 nle_obj_notfound "obj not found" //nla_put_string(msg, taskstats_cmd_attr_pid, "583"); nl_send_auto(sock, msg); nlmsg_free(msg); // specify callback 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 2 nla_put_string 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)) < 0) { printf("error parsing msg\n"); } if ((nlattr = nlattrs[taskstats_type_aggr_tgid]) || (nlattr = nlattrs[taskstats_type_aggr_pid]) || (nlattr = nlattrs[taskstats_type_null])) { stats = nla_data(nla_next(nla_data(nlattr), &rem)); printf("---\n"); printf("pid: %u\n", stats->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 attribute format received\n"); } return 0; }
the code provided works fine me, except syntax error in line 26. make sure running program root. note creating listener exiting tasks, yet reading single message, is, far understand, ack. reading socket in while(1) loop shows parsed messages whenever task exits on cpu 0.
edit: in case getting stats single pid, should use nla_put_u32 instead:
nla_put_u32(msg, taskstats_cmd_attr_pid, 583);
where 583 existing process id.
Comments
Post a Comment