Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libbpf-tools: add CO-RE 'pidpersec' #4963

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libbpf-tools/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
/offcputime
/oomkill
/opensnoop
/pidpersec
/profile
/readahead
/runqlat
Expand Down
1 change: 1 addition & 0 deletions libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ APPS = \
numamove \
offcputime \
oomkill \
pidpersec \
profile \
readahead \
runqlat \
Expand Down
16 changes: 16 additions & 0 deletions libbpf-tools/pidpersec.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2024 Tiago Ilieve
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include "pidpersec.h"

__u64 stats[S_MAXSTAT] = {};

SEC("tracepoint/sched/sched_process_fork")
int tracepoint__sched__sched_process_fork(void *ctx)
{
__atomic_add_fetch(&stats[S_COUNT], 1, __ATOMIC_RELAXED);
return 0;
}

char LICENSE[] SEC("license") = "GPL";
121 changes: 121 additions & 0 deletions libbpf-tools/pidpersec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2024 Tiago Ilieve
//
// Based on pidpersec(8) from BCC by Brendan Gregg.
// 12-Apr-2024 Tiago Ilieve Created this.
#include <argp.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <bpf/libbpf.h>
#include "pidpersec.h"
#include "pidpersec.skel.h"

static volatile sig_atomic_t exiting = 0;

struct env {
bool verbose;
} env = {};

const char *argp_program_version = "pidpersec 0.1";
const char *argp_program_bug_address =
"https://github.com/iovisor/bcc/tree/master/libbpf-tools";
const char argp_program_doc[] =
"Count new processes (via fork).\n"
"\n"
"USAGE: pidpersec [--help]\n"
"\n"
"EXAMPLES:\n"
" pidpersec # count new processes\n";

static const struct argp_option opts[] = {
{ "verbose", 'v', NULL, 0, "Verbose debug output" },
{ NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" },
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state)
{
switch (key) {
case 'v':
env.verbose = true;
break;
case 'h':
argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
if (level == LIBBPF_DEBUG && !env.verbose)
return 0;
return vfprintf(stderr, format, args);
}

static void sig_int(int signo)
{
exiting = 1;
}

int main(int argc, char **argv)
{
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
};
struct pidpersec_bpf *obj;
int err;

err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
if (err)
return err;

libbpf_set_print(libbpf_print_fn);

obj = pidpersec_bpf__open_and_load();
if (!obj) {
fprintf(stderr, "failed to open and load BPF object\n");
return 1;
}

err = pidpersec_bpf__attach(obj);
if (err) {
fprintf(stderr, "failed to attach BPF object\n");
return 1;
}

if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
err = 1;
goto cleanup;
}

/* print header */
printf("Tracing... Ctrl-C to end.\n");

while (!exiting) {
struct tm *tm;
char ts[16];
__u64 val;
time_t t;

sleep(1);

time(&t);
tm = localtime(&t);
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
val = __atomic_exchange_n(&obj->bss->stats[S_COUNT], 0, __ATOMIC_RELAXED);
printf("%s: PIDs/sec: %llu\n", ts, val);
}

cleanup:
pidpersec_bpf__destroy(obj);

return err != 0;
}
10 changes: 10 additions & 0 deletions libbpf-tools/pidpersec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __PIDPERSEC_H
#define __PIDPERSEC_H

enum stat_types {
S_COUNT = 1,
S_MAXSTAT
};

#endif /* __PIDPERSEC_H */
3 changes: 2 additions & 1 deletion man/man8/pidpersec.8
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Linux
.SH STABILITY
Unstable - in development.
.SH AUTHOR
Brendan Gregg
Brendan Gregg, original BCC Python version
Tiago Ilieve, CO-RE version
.SH SEE ALSO
top(1)
Loading