struct proc_info *parse_proc_info(FILE *fp)
{
	struct proc_info *proc = NULL;
	char *line = NULL;
	size_t len, sz = 0;
	int i, valid = 0;

	/* Strip comments & blank lines */
	while (1) {
		if ((len = getline(&line, &sz, fp)) == -1)
			break;

		i = 0;
		while (i < len && isspace(line[i++]));
		if (i >= len || line[i-1] == '#')
			continue;

		if (!proc) {
			if ((proc = alloc_proc_info()) == NULL)
				break;
		}
		if ((valid = fill_proc_info(proc, line)))
			break;
	}

	if (line)
		free(line);
	if (!valid && proc) {
		free_proc_info(proc);
		proc = NULL;
	}

	return proc;
}
Exemple #2
0
int fill_infos(struct proc_info** infos)
{
    DIR* dirp, *ddirp;
    struct dirent* dptr, *ddptr;
    __u32 pid, tid;
    int ret = -1;
    static char path[32];

    if ((dirp = opendir("/proc")) == NULL) {
        ERROR("unable to open proc \n");
        return -1;
    }

    while (dptr = readdir(dirp)) {
        char* endp;

        pid = strtoul(dptr->d_name, &endp, 10);
        if (*endp != '\0')
            continue;

        snprintf(path, sizeof(path), "/proc/%s/task/", dptr->d_name);
        if ((ddirp = opendir(path)) == NULL) {
            ERROR("Unable to open task dir\n");
            goto close;
        }

        while (ddptr = readdir(ddirp)) {
            if (strcmp(ddptr->d_name, ".") == 0 ||
                strcmp(ddptr->d_name, "..") == 0)
                continue;
            tid = strtoul(ddptr->d_name, &endp, 10);
            if (*endp != '\0') {
                ERROR("huh? %s\n", ddptr->d_name);
                goto close;
            }

            if (!(infos[tid] = alloc_proc_info())) {
                ERROR("Unable to alloc memory\n");
                goto close;
            }
            infos[tid]->tgid = pid;
            infos[tid]->pid = tid;
        }
    }
    ret = 0;

close : 
    closedir(dirp);
    dirp = NULL;
    if (ret) 
        return ret;

    for (tid = 0; tid < pid_max; tid++) {
        if (!infos[tid])
            continue;
        if (infos[tid]->updated)
            continue;

        if (tid && (ret = send_cmd(TASKSTATS_CMD_GET, TASKSTATS_CMD_ATTR_PID, \
            &tid, sizeof(__u32))) < 0) {
            ERROR("unable to send cmd to tid [%d]\n", tid);
            goto out;
        }

    retry : 
        if ((ret = recv_taskstats(0, infos)) < 0) {  //MSG_DONTWAIT
            goto out;
        }

        if (!infos[tid]->updated)
            goto retry;
    }

out : 
    return ret;
}
Exemple #3
0
int recv_taskstats(int recv_flags, struct proc_info** infos)
{
    int rep_len, len, aggr_len, len2;
    struct msgtemplate msg;
    struct nlattr* na;
    __u32 tgid = 0, pid = 0;

//recv :
    if ((rep_len = recv(nl_sd, &msg, sizeof(msg), recv_flags)) < 0) { //MSG_DONTWAIT
        //if (errno == EAGAIN) {
        //    usleep(10000);
        //    goto recv;
        //}
        //if (!(recv_flags | MSG_DONTWAIT) && rep_len == -1) {
        //}

        if ((recv_flags & MSG_DONTWAIT) && errno == EAGAIN)
            return -EAGAIN;

        ERROR("receive error %d %d\n", rep_len, errno);
        return rep_len;
    }

    //check if packet is error
    if (msg.n.nlmsg_type == NLMSG_ERROR ||
        !NLMSG_OK((&msg.n), rep_len)) {
        struct nlmsgerr* err = NLMSG_DATA(&msg);
        ERROR("fatal reply error, errno %d\n", err->error);
        return -1;
    }

    rep_len = GENLMSG_PAYLOAD(&msg.n);
    na = (struct nlattr*)GENLMSG_DATA(&msg);
    len = 0;
    
    while (len < rep_len) {
        len += NLA_ALIGN(na->nla_len);

        switch (na->nla_type) {
        case TASKSTATS_TYPE_AGGR_TGID:
            // fall through
        case TASKSTATS_TYPE_AGGR_PID:
            aggr_len = NLA_PAYLOAD(na->nla_len);
            len2 = 0;
            na = (struct nlattr*)NLA_DATA(na);

            while (len2 < aggr_len) {
                switch (na->nla_type) {
                case TASKSTATS_TYPE_PID:
                    pid = *(int*)NLA_DATA(na);
                    tgid = 0;
                    break;
                case TASKSTATS_TYPE_TGID:
                    tgid = *(int*)NLA_DATA(na);
                    pid = 0;
                    break;
                case TASKSTATS_TYPE_STATS:
                    if (tgid) {
                        break;
                    }

                    if (!infos[pid] && !(infos[pid] = alloc_proc_info())) {
                        ERROR("unable to allocate memory\n");
                        return -ENOMEM;
                    }
                    memcpy(&infos[pid]->t, (struct taskstats*)NLA_DATA(na), 
                        sizeof(struct taskstats));
                    infos[pid]->updated = 1;

                    //print_delayacct(NLA_DATA(na));
                    //print_ioacct(NLA_DATA(na));
                    break;
                default :
                    ERROR("unknown nested nla_type %d\n", na->nla_type);
                    break;
                }
                len2 += NLA_ALIGN(na->nla_len);
                na = (struct nlattr*)((char*)na + len2);
            } //end of while for TASKSTATS_TYPE_AGGR_PID packet analysis
            break;

        case CGROUPSTATS_TYPE_CGROUP_STATS:
            PRINTF("cgroup\n"); break;
        default :
            PRINTF("default %d\n", msg.n.nlmsg_type);
        case TASKSTATS_TYPE_NULL:
            break;
        } //end of switch clause

        na = (struct nlattr*)(GENLMSG_DATA(&msg) + len);
    } //end of while loop for recv'ed packet analysis

    return 0;
}