ps: add -q/q/--quick-pid option
This commit introduces a new option q/-q/--quick-pid to the 'ps' command. The option does a similar job to the p/-p/--pid option (i.e. selection of PIDs listed in the comma separated list that follows the option), but the new option is optimized for speed. In cases where users only need to specify a list of PIDs to be shown and don't need other selection options, forest type output and sorting options, the new option is recommended as it decreases the initial processing delay by avoiding reading the necessary information from all the processes running on the system and by simplifying the internal filtering logic.
This commit is contained in:
parent
6cd8691720
commit
e751606fcc
@ -41,6 +41,7 @@
|
|||||||
#define SEL_SESS 12
|
#define SEL_SESS 12
|
||||||
#define SEL_COMM 13
|
#define SEL_COMM 13
|
||||||
#define SEL_PPID 14
|
#define SEL_PPID 14
|
||||||
|
#define SEL_PID_QUICK 15
|
||||||
|
|
||||||
/* Since an enum could be smashed by a #define, it would be bad. */
|
/* Since an enum could be smashed by a #define, it would be bad. */
|
||||||
#define U98 0 /* Unix98 standard */ /* This must be 0 */
|
#define U98 0 /* Unix98 standard */ /* This must be 0 */
|
||||||
|
75
ps/display.c
75
ps/display.c
@ -164,6 +164,7 @@ static void arg_show(void){
|
|||||||
case SEL_FGID: show_gid("FGID", walk->n, walk->u); break;
|
case SEL_FGID: show_gid("FGID", walk->n, walk->u); break;
|
||||||
case SEL_PGRP: show_pid("PGRP", walk->n, walk->u); break;
|
case SEL_PGRP: show_pid("PGRP", walk->n, walk->u); break;
|
||||||
case SEL_PID : show_pid("PID ", walk->n, walk->u); break;
|
case SEL_PID : show_pid("PID ", walk->n, walk->u); break;
|
||||||
|
case SEL_PID_QUICK : show_pid("PID_QUICK ", walk->n, walk->u); break;
|
||||||
case SEL_PPID: show_pid("PPID", walk->n, walk->u); break;
|
case SEL_PPID: show_pid("PPID", walk->n, walk->u); break;
|
||||||
case SEL_TTY : show_tty("TTY ", walk->n, walk->u); break;
|
case SEL_TTY : show_tty("TTY ", walk->n, walk->u); break;
|
||||||
case SEL_SESS: show_pid("SESS", walk->n, walk->u); break;
|
case SEL_SESS: show_pid("SESS", walk->n, walk->u); break;
|
||||||
@ -343,8 +344,29 @@ static int want_this_proc_pcpu(proc_t *buf){
|
|||||||
static void simple_spew(void){
|
static void simple_spew(void){
|
||||||
static proc_t buf, buf2; // static avoids memset
|
static proc_t buf, buf2; // static avoids memset
|
||||||
PROCTAB* ptp;
|
PROCTAB* ptp;
|
||||||
|
pid_t* pidlist;
|
||||||
|
int flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
|
pidlist = NULL;
|
||||||
|
flags = needs_for_format | needs_for_sort | needs_for_select | needs_for_threads;
|
||||||
|
|
||||||
|
// -q option (only single SEL_PID_QUICK typecode entry expected in the list, if present)
|
||||||
|
if (selection_list && selection_list->typecode == SEL_PID_QUICK) {
|
||||||
|
flags |= PROC_PID;
|
||||||
|
|
||||||
|
pidlist = (pid_t*) malloc(selection_list->n * sizeof(pid_t));
|
||||||
|
if (!pidlist) {
|
||||||
|
fprintf(stderr, _("error: not enough memory\n"));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < selection_list->n; i++) {
|
||||||
|
pidlist[i] = selection_list->u[selection_list->n-i-1].pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptp = openproc(flags, pidlist);
|
||||||
if(!ptp) {
|
if(!ptp) {
|
||||||
fprintf(stderr, _("error: can not access /proc\n"));
|
fprintf(stderr, _("error: can not access /proc\n"));
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -385,6 +407,8 @@ static void simple_spew(void){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
closeproc(ptp);
|
closeproc(ptp);
|
||||||
|
|
||||||
|
if (pidlist) free(pidlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** forest output requires sorting by ppid; add start_time by default */
|
/***** forest output requires sorting by ppid; add start_time by default */
|
||||||
@ -539,6 +563,52 @@ static void fancy_spew(void){
|
|||||||
closeproc(ptp);
|
closeproc(ptp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void arg_check_conflicts(void)
|
||||||
|
{
|
||||||
|
int selection_list_len;
|
||||||
|
int has_quick_pid;
|
||||||
|
|
||||||
|
selection_node *walk = selection_list;
|
||||||
|
has_quick_pid = 0;
|
||||||
|
selection_list_len = 0;
|
||||||
|
|
||||||
|
while (walk) {
|
||||||
|
if (walk->typecode == SEL_PID_QUICK) has_quick_pid++;
|
||||||
|
walk = walk->next;
|
||||||
|
selection_list_len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -q doesn't allow multiple occurences */
|
||||||
|
if (has_quick_pid > 1) {
|
||||||
|
fprintf(stderr, "q/-q/--quick-pid can only be used once.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -q doesn't allow combinations with other selection switches */
|
||||||
|
if (has_quick_pid && selection_list_len > has_quick_pid) {
|
||||||
|
fprintf(stderr, "q/-q/--quick-pid cannot be combined with other selection options.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -q cannot be used with forest type listings */
|
||||||
|
if (has_quick_pid && forest_type) {
|
||||||
|
fprintf(stderr, "q/-q/--quick-pid cannot be used together with forest type listings.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -q cannot be used with sort */
|
||||||
|
if (has_quick_pid && sort_list) {
|
||||||
|
fprintf(stderr, "q/-q,--quick-pid cannot be used together with sort options.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -q cannot be used with -N */
|
||||||
|
if (has_quick_pid && negate_selection) {
|
||||||
|
fprintf(stderr, "q/-q/--quick-pid cannot be used together with negation switches.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/***** no comment */
|
/***** no comment */
|
||||||
int main(int argc, char *argv[]){
|
int main(int argc, char *argv[]){
|
||||||
@ -580,6 +650,9 @@ int main(int argc, char *argv[]){
|
|||||||
reset_global(); /* must be before parser */
|
reset_global(); /* must be before parser */
|
||||||
arg_parse(argc,argv);
|
arg_parse(argc,argv);
|
||||||
|
|
||||||
|
/* check for invalid combination of arguments */
|
||||||
|
arg_check_conflicts();
|
||||||
|
|
||||||
/* arg_show(); */
|
/* arg_show(); */
|
||||||
trace("screen is %ux%u\n",screen_cols,screen_rows);
|
trace("screen is %ux%u\n",screen_cols,screen_rows);
|
||||||
/* printf("sizeof(proc_t) is %d.\n", sizeof(proc_t)); */
|
/* printf("sizeof(proc_t) is %d.\n", sizeof(proc_t)); */
|
||||||
|
@ -111,8 +111,10 @@ void do_help (const char *opt, int rc) {
|
|||||||
fputs(_(" -C <command> command name\n"), out);
|
fputs(_(" -C <command> command name\n"), out);
|
||||||
fputs(_(" -G, --Group <GID> real group id or name\n"), out);
|
fputs(_(" -G, --Group <GID> real group id or name\n"), out);
|
||||||
fputs(_(" -g, --group <group> session or effective group name\n"), out);
|
fputs(_(" -g, --group <group> session or effective group name\n"), out);
|
||||||
fputs(_(" -p, --pid <PID> process id\n"), out);
|
fputs(_(" -p, p, --pid <PID> process id\n"), out);
|
||||||
fputs(_(" --ppid <PID> select by parent process id\n"), out);
|
fputs(_(" --ppid <PID> parent process id\n"), out);
|
||||||
|
fputs(_(" -q, q, --quick-pid <PID>\n"
|
||||||
|
" process id (quick mode)\n"), out);
|
||||||
fputs(_(" -s, --sid <session> session id\n"), out);
|
fputs(_(" -s, --sid <session> session id\n"), out);
|
||||||
fputs(_(" -t, t, --tty <tty> terminal\n"), out);
|
fputs(_(" -t, t, --tty <tty> terminal\n"), out);
|
||||||
fputs(_(" -u, U, --user <UID> effective user id or name\n"), out);
|
fputs(_(" -u, U, --user <UID> effective user id or name\n"), out);
|
||||||
|
25
ps/parser.c
25
ps/parser.c
@ -426,6 +426,14 @@ static const char *parse_sysv_option(void){
|
|||||||
if(err) return err;
|
if(err) return err;
|
||||||
selection_list->typecode = SEL_PID;
|
selection_list->typecode = SEL_PID;
|
||||||
return NULL; /* can't have any more options */
|
return NULL; /* can't have any more options */
|
||||||
|
case 'q': /* end */
|
||||||
|
trace("-q quick select by PID.\n");
|
||||||
|
arg=get_opt_arg();
|
||||||
|
if(!arg) return "List of process IDs must follow -q.";
|
||||||
|
err=parse_list(arg, parse_pid);
|
||||||
|
if(err) return err;
|
||||||
|
selection_list->typecode = SEL_PID_QUICK;
|
||||||
|
return NULL; /* can't have any more options */
|
||||||
#if 0
|
#if 0
|
||||||
case 'r':
|
case 'r':
|
||||||
trace("-r some Digital Unix thing about warnings...\n");
|
trace("-r some Digital Unix thing about warnings...\n");
|
||||||
@ -696,6 +704,14 @@ static const char *parse_bsd_option(void){
|
|||||||
if(err) return err;
|
if(err) return err;
|
||||||
selection_list->typecode = SEL_PID;
|
selection_list->typecode = SEL_PID;
|
||||||
return NULL; /* can't have any more options */
|
return NULL; /* can't have any more options */
|
||||||
|
case 'q': /* end */
|
||||||
|
trace("q Quick select by process ID\n");
|
||||||
|
arg=get_opt_arg();
|
||||||
|
if(!arg) return "List of process IDs must follow q.";
|
||||||
|
err=parse_list(arg, parse_pid);
|
||||||
|
if(err) return err;
|
||||||
|
selection_list->typecode = SEL_PID_QUICK;
|
||||||
|
return NULL; /* can't have any more options */
|
||||||
case 'r':
|
case 'r':
|
||||||
trace("r select running processes\n");
|
trace("r select running processes\n");
|
||||||
running_only = 1;
|
running_only = 1;
|
||||||
@ -820,6 +836,7 @@ static const char *parse_gnu_option(void){
|
|||||||
{"noheadings", &&case_noheadings},
|
{"noheadings", &&case_noheadings},
|
||||||
{"pid", &&case_pid},
|
{"pid", &&case_pid},
|
||||||
{"ppid", &&case_ppid},
|
{"ppid", &&case_ppid},
|
||||||
|
{"quick-pid", &&case_pid_quick},
|
||||||
{"rows", &&case_rows},
|
{"rows", &&case_rows},
|
||||||
{"sid", &&case_sid},
|
{"sid", &&case_sid},
|
||||||
{"sort", &&case_sort},
|
{"sort", &&case_sort},
|
||||||
@ -949,6 +966,14 @@ static const char *parse_gnu_option(void){
|
|||||||
if(err) return err;
|
if(err) return err;
|
||||||
selection_list->typecode = SEL_PID;
|
selection_list->typecode = SEL_PID;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
case_pid_quick:
|
||||||
|
trace("--quick-pid\n");
|
||||||
|
arg = grab_gnu_arg();
|
||||||
|
if(!arg) return "List of process IDs must follow --quick-pid.";
|
||||||
|
err=parse_list(arg, parse_pid);
|
||||||
|
if(err) return err;
|
||||||
|
selection_list->typecode = SEL_PID_QUICK;
|
||||||
|
return NULL;
|
||||||
case_ppid:
|
case_ppid:
|
||||||
trace("--ppid\n");
|
trace("--ppid\n");
|
||||||
arg = grab_gnu_arg();
|
arg = grab_gnu_arg();
|
||||||
|
27
ps/ps.1
27
ps/ps.1
@ -143,7 +143,7 @@ Print only the process IDs of syslogd:
|
|||||||
.B ps\ \-C\ syslogd\ \-o\ pid=
|
.B ps\ \-C\ syslogd\ \-o\ pid=
|
||||||
.TP
|
.TP
|
||||||
Print only the name of PID 42:
|
Print only the name of PID 42:
|
||||||
.B ps\ \-p\ 42\ \-o\ comm=
|
.B ps\ \-q\ 42\ \-o\ comm=
|
||||||
.PP
|
.PP
|
||||||
.PP
|
.PP
|
||||||
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
@ -305,6 +305,31 @@ process\ ID in
|
|||||||
That is, it selects processes that are children of those listed in
|
That is, it selects processes that are children of those listed in
|
||||||
.IR pidlist .
|
.IR pidlist .
|
||||||
.TP
|
.TP
|
||||||
|
.BI q \ pidlist
|
||||||
|
Select by process ID (quick mode). Identical to
|
||||||
|
.B \-q
|
||||||
|
and
|
||||||
|
.BR \-\-quick\-pid .
|
||||||
|
.TP
|
||||||
|
.BI \-q \ pidlist
|
||||||
|
Select by PID (quick mode). This selects the processes whose process ID numbers appear in
|
||||||
|
.IR pidlist .
|
||||||
|
With this option \fBps\fR reads the necessary info only
|
||||||
|
for the pids listed in the \fIpidlist\fR and doesn't apply
|
||||||
|
additional filtering rules. The order of pids is unsorted
|
||||||
|
and preserved. No additional selection options, sorting
|
||||||
|
and forest type listings are allowed in this mode.
|
||||||
|
Identical to
|
||||||
|
.B q
|
||||||
|
and
|
||||||
|
.BR \-\-quick\-pid .
|
||||||
|
.TP
|
||||||
|
.BI \-\-quick\-pid \ pidlist
|
||||||
|
Select by process\ ID (quick mode). Identical to
|
||||||
|
.B \-q
|
||||||
|
and
|
||||||
|
.BR q .
|
||||||
|
.TP
|
||||||
.BI \-s \ sesslist
|
.BI \-s \ sesslist
|
||||||
Select by session ID. This selects the processes with a session ID specified
|
Select by session ID. This selects the processes with a session ID specified
|
||||||
in
|
in
|
||||||
|
@ -111,6 +111,7 @@ static int proc_was_listed(proc_t *buf){
|
|||||||
|
|
||||||
break; case SEL_PGRP: return_if_match(pgrp,pid);
|
break; case SEL_PGRP: return_if_match(pgrp,pid);
|
||||||
break; case SEL_PID : return_if_match(tgid,pid);
|
break; case SEL_PID : return_if_match(tgid,pid);
|
||||||
|
break; case SEL_PID_QUICK : return_if_match(tgid,pid);
|
||||||
break; case SEL_PPID: return_if_match(ppid,ppid);
|
break; case SEL_PPID: return_if_match(ppid,ppid);
|
||||||
break; case SEL_TTY : return_if_match(tty,tty);
|
break; case SEL_TTY : return_if_match(tty,tty);
|
||||||
break; case SEL_SESS: return_if_match(session,pid);
|
break; case SEL_SESS: return_if_match(session,pid);
|
||||||
|
Loading…
Reference in New Issue
Block a user