~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/perf.c

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * perf.c
  3  *
  4  * Performance analysis utility.
  5  *
  6  * This is the main hub from which the sub-commands (perf stat,
  7  * perf top, perf record, perf report, etc.) are started.
  8  */
  9 #include "builtin.h"
 10 
 11 #include "util/env.h"
 12 #include <subcmd/exec-cmd.h>
 13 #include "util/cache.h"
 14 #include "util/quote.h"
 15 #include <subcmd/run-command.h>
 16 #include "util/parse-events.h"
 17 #include <subcmd/parse-options.h>
 18 #include "util/bpf-loader.h"
 19 #include "util/debug.h"
 20 #include <api/fs/tracing_path.h>
 21 #include <pthread.h>
 22 #include <stdlib.h>
 23 #include <time.h>
 24 
 25 const char perf_usage_string[] =
 26         "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
 27 
 28 const char perf_more_info_string[] =
 29         "See 'perf help COMMAND' for more information on a specific command.";
 30 
 31 int use_browser = -1;
 32 static int use_pager = -1;
 33 const char *input_name;
 34 
 35 struct cmd_struct {
 36         const char *cmd;
 37         int (*fn)(int, const char **, const char *);
 38         int option;
 39 };
 40 
 41 static struct cmd_struct commands[] = {
 42         { "buildid-cache", cmd_buildid_cache, 0 },
 43         { "buildid-list", cmd_buildid_list, 0 },
 44         { "config",     cmd_config,     0 },
 45         { "diff",       cmd_diff,       0 },
 46         { "evlist",     cmd_evlist,     0 },
 47         { "help",       cmd_help,       0 },
 48         { "list",       cmd_list,       0 },
 49         { "record",     cmd_record,     0 },
 50         { "report",     cmd_report,     0 },
 51         { "bench",      cmd_bench,      0 },
 52         { "stat",       cmd_stat,       0 },
 53         { "timechart",  cmd_timechart,  0 },
 54         { "top",        cmd_top,        0 },
 55         { "annotate",   cmd_annotate,   0 },
 56         { "version",    cmd_version,    0 },
 57         { "script",     cmd_script,     0 },
 58         { "sched",      cmd_sched,      0 },
 59 #ifdef HAVE_LIBELF_SUPPORT
 60         { "probe",      cmd_probe,      0 },
 61 #endif
 62         { "kmem",       cmd_kmem,       0 },
 63         { "lock",       cmd_lock,       0 },
 64         { "kvm",        cmd_kvm,        0 },
 65         { "test",       cmd_test,       0 },
 66 #ifdef HAVE_LIBAUDIT_SUPPORT
 67         { "trace",      cmd_trace,      0 },
 68 #endif
 69         { "inject",     cmd_inject,     0 },
 70         { "mem",        cmd_mem,        0 },
 71         { "data",       cmd_data,       0 },
 72 };
 73 
 74 struct pager_config {
 75         const char *cmd;
 76         int val;
 77 };
 78 
 79 static int pager_command_config(const char *var, const char *value, void *data)
 80 {
 81         struct pager_config *c = data;
 82         if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
 83                 c->val = perf_config_bool(var, value);
 84         return 0;
 85 }
 86 
 87 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
 88 int check_pager_config(const char *cmd)
 89 {
 90         struct pager_config c;
 91         c.cmd = cmd;
 92         c.val = -1;
 93         perf_config(pager_command_config, &c);
 94         return c.val;
 95 }
 96 
 97 static int browser_command_config(const char *var, const char *value, void *data)
 98 {
 99         struct pager_config *c = data;
100         if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd))
101                 c->val = perf_config_bool(var, value);
102         if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd))
103                 c->val = perf_config_bool(var, value) ? 2 : 0;
104         return 0;
105 }
106 
107 /*
108  * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
109  * and -1 for "not specified"
110  */
111 static int check_browser_config(const char *cmd)
112 {
113         struct pager_config c;
114         c.cmd = cmd;
115         c.val = -1;
116         perf_config(browser_command_config, &c);
117         return c.val;
118 }
119 
120 static void commit_pager_choice(void)
121 {
122         switch (use_pager) {
123         case 0:
124                 setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
125                 break;
126         case 1:
127                 /* setup_pager(); */
128                 break;
129         default:
130                 break;
131         }
132 }
133 
134 struct option options[] = {
135         OPT_ARGUMENT("help", "help"),
136         OPT_ARGUMENT("version", "version"),
137         OPT_ARGUMENT("exec-path", "exec-path"),
138         OPT_ARGUMENT("html-path", "html-path"),
139         OPT_ARGUMENT("paginate", "paginate"),
140         OPT_ARGUMENT("no-pager", "no-pager"),
141         OPT_ARGUMENT("perf-dir", "perf-dir"),
142         OPT_ARGUMENT("work-tree", "work-tree"),
143         OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
144         OPT_ARGUMENT("buildid-dir", "buildid-dir"),
145         OPT_ARGUMENT("list-cmds", "list-cmds"),
146         OPT_ARGUMENT("list-opts", "list-opts"),
147         OPT_ARGUMENT("debug", "debug"),
148         OPT_END()
149 };
150 
151 static int handle_options(const char ***argv, int *argc, int *envchanged)
152 {
153         int handled = 0;
154 
155         while (*argc > 0) {
156                 const char *cmd = (*argv)[0];
157                 if (cmd[0] != '-')
158                         break;
159 
160                 /*
161                  * For legacy reasons, the "version" and "help"
162                  * commands can be written with "--" prepended
163                  * to make them look like flags.
164                  */
165                 if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
166                         break;
167 
168                 /*
169                  * Shortcut for '-h' and '-v' options to invoke help
170                  * and version command.
171                  */
172                 if (!strcmp(cmd, "-h")) {
173                         (*argv)[0] = "--help";
174                         break;
175                 }
176 
177                 if (!strcmp(cmd, "-v")) {
178                         (*argv)[0] = "--version";
179                         break;
180                 }
181 
182                 /*
183                  * Check remaining flags.
184                  */
185                 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
186                         cmd += strlen(CMD_EXEC_PATH);
187                         if (*cmd == '=')
188                                 set_argv_exec_path(cmd + 1);
189                         else {
190                                 puts(get_argv_exec_path());
191                                 exit(0);
192                         }
193                 } else if (!strcmp(cmd, "--html-path")) {
194                         puts(system_path(PERF_HTML_PATH));
195                         exit(0);
196                 } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
197                         use_pager = 1;
198                 } else if (!strcmp(cmd, "--no-pager")) {
199                         use_pager = 0;
200                         if (envchanged)
201                                 *envchanged = 1;
202                 } else if (!strcmp(cmd, "--perf-dir")) {
203                         if (*argc < 2) {
204                                 fprintf(stderr, "No directory given for --perf-dir.\n");
205                                 usage(perf_usage_string);
206                         }
207                         setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
208                         if (envchanged)
209                                 *envchanged = 1;
210                         (*argv)++;
211                         (*argc)--;
212                         handled++;
213                 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
214                         setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
215                         if (envchanged)
216                                 *envchanged = 1;
217                 } else if (!strcmp(cmd, "--work-tree")) {
218                         if (*argc < 2) {
219                                 fprintf(stderr, "No directory given for --work-tree.\n");
220                                 usage(perf_usage_string);
221                         }
222                         setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
223                         if (envchanged)
224                                 *envchanged = 1;
225                         (*argv)++;
226                         (*argc)--;
227                 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
228                         setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
229                         if (envchanged)
230                                 *envchanged = 1;
231                 } else if (!strcmp(cmd, "--debugfs-dir")) {
232                         if (*argc < 2) {
233                                 fprintf(stderr, "No directory given for --debugfs-dir.\n");
234                                 usage(perf_usage_string);
235                         }
236                         tracing_path_set((*argv)[1]);
237                         if (envchanged)
238                                 *envchanged = 1;
239                         (*argv)++;
240                         (*argc)--;
241                 } else if (!strcmp(cmd, "--buildid-dir")) {
242                         if (*argc < 2) {
243                                 fprintf(stderr, "No directory given for --buildid-dir.\n");
244                                 usage(perf_usage_string);
245                         }
246                         set_buildid_dir((*argv)[1]);
247                         if (envchanged)
248                                 *envchanged = 1;
249                         (*argv)++;
250                         (*argc)--;
251                 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
252                         tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
253                         fprintf(stderr, "dir: %s\n", tracing_path);
254                         if (envchanged)
255                                 *envchanged = 1;
256                 } else if (!strcmp(cmd, "--list-cmds")) {
257                         unsigned int i;
258 
259                         for (i = 0; i < ARRAY_SIZE(commands); i++) {
260                                 struct cmd_struct *p = commands+i;
261                                 printf("%s ", p->cmd);
262                         }
263                         putchar('\n');
264                         exit(0);
265                 } else if (!strcmp(cmd, "--list-opts")) {
266                         unsigned int i;
267 
268                         for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
269                                 struct option *p = options+i;
270                                 printf("--%s ", p->long_name);
271                         }
272                         putchar('\n');
273                         exit(0);
274                 } else if (!strcmp(cmd, "--debug")) {
275                         if (*argc < 2) {
276                                 fprintf(stderr, "No variable specified for --debug.\n");
277                                 usage(perf_usage_string);
278                         }
279                         if (perf_debug_option((*argv)[1]))
280                                 usage(perf_usage_string);
281 
282                         (*argv)++;
283                         (*argc)--;
284                 } else {
285                         fprintf(stderr, "Unknown option: %s\n", cmd);
286                         usage(perf_usage_string);
287                 }
288 
289                 (*argv)++;
290                 (*argc)--;
291                 handled++;
292         }
293         return handled;
294 }
295 
296 static int handle_alias(int *argcp, const char ***argv)
297 {
298         int envchanged = 0, ret = 0, saved_errno = errno;
299         int count, option_count;
300         const char **new_argv;
301         const char *alias_command;
302         char *alias_string;
303 
304         alias_command = (*argv)[0];
305         alias_string = alias_lookup(alias_command);
306         if (alias_string) {
307                 if (alias_string[0] == '!') {
308                         if (*argcp > 1) {
309                                 struct strbuf buf;
310 
311                                 strbuf_init(&buf, PATH_MAX);
312                                 strbuf_addstr(&buf, alias_string);
313                                 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
314                                 free(alias_string);
315                                 alias_string = buf.buf;
316                         }
317                         ret = system(alias_string + 1);
318                         if (ret >= 0 && WIFEXITED(ret) &&
319                             WEXITSTATUS(ret) != 127)
320                                 exit(WEXITSTATUS(ret));
321                         die("Failed to run '%s' when expanding alias '%s'",
322                             alias_string + 1, alias_command);
323                 }
324                 count = split_cmdline(alias_string, &new_argv);
325                 if (count < 0)
326                         die("Bad alias.%s string", alias_command);
327                 option_count = handle_options(&new_argv, &count, &envchanged);
328                 if (envchanged)
329                         die("alias '%s' changes environment variables\n"
330                                  "You can use '!perf' in the alias to do this.",
331                                  alias_command);
332                 memmove(new_argv - option_count, new_argv,
333                                 count * sizeof(char *));
334                 new_argv -= option_count;
335 
336                 if (count < 1)
337                         die("empty alias for %s", alias_command);
338 
339                 if (!strcmp(alias_command, new_argv[0]))
340                         die("recursive alias: %s", alias_command);
341 
342                 new_argv = realloc(new_argv, sizeof(char *) *
343                                     (count + *argcp + 1));
344                 /* insert after command name */
345                 memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
346                 new_argv[count + *argcp] = NULL;
347 
348                 *argv = new_argv;
349                 *argcp += count - 1;
350 
351                 ret = 1;
352         }
353 
354         errno = saved_errno;
355 
356         return ret;
357 }
358 
359 const char perf_version_string[] = PERF_VERSION;
360 
361 #define RUN_SETUP       (1<<0)
362 #define USE_PAGER       (1<<1)
363 /*
364  * require working tree to be present -- anything uses this needs
365  * RUN_SETUP for reading from the configuration file.
366  */
367 #define NEED_WORK_TREE  (1<<2)
368 
369 static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
370 {
371         int status;
372         struct stat st;
373         const char *prefix;
374         char sbuf[STRERR_BUFSIZE];
375 
376         prefix = NULL;
377         if (p->option & RUN_SETUP)
378                 prefix = NULL; /* setup_perf_directory(); */
379 
380         if (use_browser == -1)
381                 use_browser = check_browser_config(p->cmd);
382 
383         if (use_pager == -1 && p->option & RUN_SETUP)
384                 use_pager = check_pager_config(p->cmd);
385         if (use_pager == -1 && p->option & USE_PAGER)
386                 use_pager = 1;
387         commit_pager_choice();
388 
389         perf_env__set_cmdline(&perf_env, argc, argv);
390         status = p->fn(argc, argv, prefix);
391         exit_browser(status);
392         perf_env__exit(&perf_env);
393         bpf__clear();
394 
395         if (status)
396                 return status & 0xff;
397 
398         /* Somebody closed stdout? */
399         if (fstat(fileno(stdout), &st))
400                 return 0;
401         /* Ignore write errors for pipes and sockets.. */
402         if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
403                 return 0;
404 
405         status = 1;
406         /* Check for ENOSPC and EIO errors.. */
407         if (fflush(stdout)) {
408                 fprintf(stderr, "write failure on standard output: %s",
409                         strerror_r(errno, sbuf, sizeof(sbuf)));
410                 goto out;
411         }
412         if (ferror(stdout)) {
413                 fprintf(stderr, "unknown write failure on standard output");
414                 goto out;
415         }
416         if (fclose(stdout)) {
417                 fprintf(stderr, "close failed on standard output: %s",
418                         strerror_r(errno, sbuf, sizeof(sbuf)));
419                 goto out;
420         }
421         status = 0;
422 out:
423         return status;
424 }
425 
426 static void handle_internal_command(int argc, const char **argv)
427 {
428         const char *cmd = argv[0];
429         unsigned int i;
430         static const char ext[] = STRIP_EXTENSION;
431 
432         if (sizeof(ext) > 1) {
433                 i = strlen(argv[0]) - strlen(ext);
434                 if (i > 0 && !strcmp(argv[0] + i, ext)) {
435                         char *argv0 = strdup(argv[0]);
436                         argv[0] = cmd = argv0;
437                         argv0[i] = '\0';
438                 }
439         }
440 
441         /* Turn "perf cmd --help" into "perf help cmd" */
442         if (argc > 1 && !strcmp(argv[1], "--help")) {
443                 argv[1] = argv[0];
444                 argv[0] = cmd = "help";
445         }
446 
447         for (i = 0; i < ARRAY_SIZE(commands); i++) {
448                 struct cmd_struct *p = commands+i;
449                 if (strcmp(p->cmd, cmd))
450                         continue;
451                 exit(run_builtin(p, argc, argv));
452         }
453 }
454 
455 static void execv_dashed_external(const char **argv)
456 {
457         struct strbuf cmd = STRBUF_INIT;
458         const char *tmp;
459         int status;
460 
461         strbuf_addf(&cmd, "perf-%s", argv[0]);
462 
463         /*
464          * argv[0] must be the perf command, but the argv array
465          * belongs to the caller, and may be reused in
466          * subsequent loop iterations. Save argv[0] and
467          * restore it on error.
468          */
469         tmp = argv[0];
470         argv[0] = cmd.buf;
471 
472         /*
473          * if we fail because the command is not found, it is
474          * OK to return. Otherwise, we just pass along the status code.
475          */
476         status = run_command_v_opt(argv, 0);
477         if (status != -ERR_RUN_COMMAND_EXEC) {
478                 if (IS_RUN_COMMAND_ERR(status))
479                         die("unable to run '%s'", argv[0]);
480                 exit(-status);
481         }
482         errno = ENOENT; /* as if we called execvp */
483 
484         argv[0] = tmp;
485 
486         strbuf_release(&cmd);
487 }
488 
489 static int run_argv(int *argcp, const char ***argv)
490 {
491         int done_alias = 0;
492 
493         while (1) {
494                 /* See if it's an internal command */
495                 handle_internal_command(*argcp, *argv);
496 
497                 /* .. then try the external ones */
498                 execv_dashed_external(*argv);
499 
500                 /* It could be an alias -- this works around the insanity
501                  * of overriding "perf log" with "perf show" by having
502                  * alias.log = show
503                  */
504                 if (done_alias || !handle_alias(argcp, argv))
505                         break;
506                 done_alias = 1;
507         }
508 
509         return done_alias;
510 }
511 
512 static void pthread__block_sigwinch(void)
513 {
514         sigset_t set;
515 
516         sigemptyset(&set);
517         sigaddset(&set, SIGWINCH);
518         pthread_sigmask(SIG_BLOCK, &set, NULL);
519 }
520 
521 void pthread__unblock_sigwinch(void)
522 {
523         sigset_t set;
524 
525         sigemptyset(&set);
526         sigaddset(&set, SIGWINCH);
527         pthread_sigmask(SIG_UNBLOCK, &set, NULL);
528 }
529 
530 int main(int argc, const char **argv)
531 {
532         const char *cmd;
533         char sbuf[STRERR_BUFSIZE];
534 
535         /* libsubcmd init */
536         exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
537         pager_init(PERF_PAGER_ENVIRONMENT);
538 
539         /* The page_size is placed in util object. */
540         page_size = sysconf(_SC_PAGE_SIZE);
541         cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
542 
543         cmd = extract_argv0_path(argv[0]);
544         if (!cmd)
545                 cmd = "perf-help";
546 
547         srandom(time(NULL));
548 
549         /* get debugfs/tracefs mount point from /proc/mounts */
550         tracing_path_mount();
551 
552         /*
553          * "perf-xxxx" is the same as "perf xxxx", but we obviously:
554          *
555          *  - cannot take flags in between the "perf" and the "xxxx".
556          *  - cannot execute it externally (since it would just do
557          *    the same thing over again)
558          *
559          * So we just directly call the internal command handler, and
560          * die if that one cannot handle it.
561          */
562         if (!prefixcmp(cmd, "perf-")) {
563                 cmd += 5;
564                 argv[0] = cmd;
565                 handle_internal_command(argc, argv);
566                 fprintf(stderr, "cannot handle %s internally", cmd);
567                 goto out;
568         }
569         if (!prefixcmp(cmd, "trace")) {
570 #ifdef HAVE_LIBAUDIT_SUPPORT
571                 set_buildid_dir(NULL);
572                 setup_path();
573                 argv[0] = "trace";
574                 return cmd_trace(argc, argv, NULL);
575 #else
576                 fprintf(stderr,
577                         "trace command not available: missing audit-libs devel package at build time.\n");
578                 goto out;
579 #endif
580         }
581         /* Look for flags.. */
582         argv++;
583         argc--;
584         handle_options(&argv, &argc, NULL);
585         commit_pager_choice();
586         set_buildid_dir(NULL);
587 
588         if (argc > 0) {
589                 if (!prefixcmp(argv[0], "--"))
590                         argv[0] += 2;
591         } else {
592                 /* The user didn't specify a command; give them help */
593                 printf("\n usage: %s\n\n", perf_usage_string);
594                 list_common_cmds_help();
595                 printf("\n %s\n\n", perf_more_info_string);
596                 goto out;
597         }
598         cmd = argv[0];
599 
600         test_attr__init();
601 
602         /*
603          * We use PATH to find perf commands, but we prepend some higher
604          * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
605          * environment, and the $(perfexecdir) from the Makefile at build
606          * time.
607          */
608         setup_path();
609         /*
610          * Block SIGWINCH notifications so that the thread that wants it can
611          * unblock and get syscalls like select interrupted instead of waiting
612          * forever while the signal goes to some other non interested thread.
613          */
614         pthread__block_sigwinch();
615 
616         while (1) {
617                 static int done_help;
618                 int was_alias = run_argv(&argc, &argv);
619 
620                 if (errno != ENOENT)
621                         break;
622 
623                 if (was_alias) {
624                         fprintf(stderr, "Expansion of alias '%s' failed; "
625                                 "'%s' is not a perf-command\n",
626                                 cmd, argv[0]);
627                         goto out;
628                 }
629                 if (!done_help) {
630                         cmd = argv[0] = help_unknown_cmd(cmd);
631                         done_help = 1;
632                 } else
633                         break;
634         }
635 
636         fprintf(stderr, "Failed to run command '%s': %s\n",
637                 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
638 out:
639         return 1;
640 }
641 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp