ps
é definido no pacote procps
no Linux.
Existe o código que processa os sinalizadores% e -c
e -l
e a prioridade:
if(format_modifiers & FM_c){
PUSH("pri"); PUSH("class");
}else if(format_flags & FF_Ul){
PUSH("ni");
if(personality & PER_IRIX_l) PUSH("priority");
else /* is this good? */ PUSH("opri");
}
Então, se você usa -c
, você obtém o campo pri
.
Se você usar -l, você receberá o sinal priority
(como IRIX) ou opri
( é bom? )
Em outras palavras, você não está olhando para os mesmos dados e é por isso que obtém resultados diferentes.
No arquivo display.c
, vemos este comentário:
// "PRI" is created by "opri", or by "pri" when -c is used.
//
// Unix98 only specifies that a high "PRI" is low priority.
// Sun and SCO add the -c behavior. Sun defines "pri" and "opri".
// Linux may use "priority" for historical purposes.
Portanto, você deve usar -o opri
em vez de -o pri
na sua linha de comando.
Para comparar essas prioridades, você pode usar a opção de linha de comando -o
com:
ps -e -o pri,opri,intpri,priority,ni,pcpu,pid,comm | less
Na verdade, existem mais algumas prioridades ... Aqui está o código que exibe essas colunas. Ele está sempre usando o valor pp->priority
, apenas altera o sinal ou adiciona / subtrai um número a ele. O único direto é priority
("prioridade Pure Linux").
// legal as UNIX "PRI"
// "priority" (was -20..20, now -100..39)
static int pr_priority(char *restrict const outbuf, const proc_t *restrict const pp){ /* -20..20 */
return snprintf(outbuf, COLWID, "%ld", pp->priority);
}
// legal as UNIX "PRI"
// "intpri" and "opri" (was 39..79, now -40..99)
static int pr_opri(char *restrict const outbuf, const proc_t *restrict const pp){ /* 39..79 */
return snprintf(outbuf, COLWID, "%ld", 60 + pp->priority);
}
// legal as UNIX "PRI"
// "pri_foo" -- match up w/ nice values of sleeping processes (-120..19)
static int pr_pri_foo(char *restrict const outbuf, const proc_t *restrict const pp){
return snprintf(outbuf, COLWID, "%ld", pp->priority - 20);
}
// legal as UNIX "PRI"
// "pri_bar" -- makes RT pri show as negative (-99..40)
static int pr_pri_bar(char *restrict const outbuf, const proc_t *restrict const pp){
return snprintf(outbuf, COLWID, "%ld", pp->priority + 1);
}
// legal as UNIX "PRI"
// "pri_baz" -- the kernel's ->prio value, as of Linux 2.6.8 (1..140)
static int pr_pri_baz(char *restrict const outbuf, const proc_t *restrict const pp){
return snprintf(outbuf, COLWID, "%ld", pp->priority + 100);
}
// not legal as UNIX "PRI"
// "pri" (was 20..60, now 0..139)
static int pr_pri(char *restrict const outbuf, const proc_t *restrict const pp){ /* 20..60 */
return snprintf(outbuf, COLWID, "%ld", 39 - pp->priority);
}
// not legal as UNIX "PRI"
// "pri_api" -- match up w/ RT API (-40..99)
static int pr_pri_api(char *restrict const outbuf, const proc_t *restrict const pp){
return snprintf(outbuf, COLWID, "%ld", -1 - pp->priority);
}
Então vemos
- "prioridade" - prioridade direta do Linux (-100 a 39)
- "intpri", "opri" - prioridade do Linux + 60 (-40 a 99)
- "pri_foo" - prioridade do Linux - 20 (-120 a 19)
- "pri_bar" - prioridade do Linux + 1 (-99 a 40)
- "pri_baz" - prioridade do Linux + 100 (1 a 140)
- "pri" - 39 - Prioridade do Linux (0 a 139, REVERSED)
- "pri_api" - -1 - Prioridade do Linux (-40 a 99, REVERSED)
Os dois últimos ("pri" e "pri_api") são considerados "ilegais" no Unix.
Quanto ao local de origem desses dados, ele é encontrado no arquivo /proc/<id>/stat
. O arquivo é lido e a única linha de texto é analisada pela seguinte chamada sscanf()
após ignorar o ID e o nome do processo (que está entre parênteses).
Vemos que um parâmetro é &P->priority
. Então o 18º parâmetro (16º após pular o ID e o nome), começando em 1.
num = sscanf(S,
"%c "
"%d %d %d %d %d "
"%lu %lu %lu %lu %lu "
"%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */
"%ld %ld "
"%d "
"%ld "
"%Lu " /* start_time */
"%lu "
"%ld "
"%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u "
"%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
"%"KLF"u %*u %*u "
"%d %d "
"%lu %lu",
&P->state,
&P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
&P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
&P->utime, &P->stime, &P->cutime, &P->cstime,
&P->priority, &P->nice,
&P->nlwp,
&P->alarm,
&P->start_time,
&P->vsize,
&P->rss,
&P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,
/* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */
&P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up */
/* -- Linux 2.0.35 ends here -- */
&P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */
/* -- Linux 2.2.8 to 2.5.17 end here -- */
&P->rtprio, &P->sched /* both added to 2.5.18 */
);
Há um exemplo dos dados que o libprocps
lê:
$ cat /proc/1/stat
1 (systemd) S 0 1 1 0 -1 4194560 188421 1692322137 105 191899 1093 466 35079020 6527486 20 0 1 0 2 341475328 1402 18446744073709551615 1 1 0 0 0 0 671173123 4096 1260 0 0 0 17 2 0 0 3606 0 0 0 0 0 0 0 0 0 0
Portanto, o processo 1 tem uma prioridade de 20. Quando convertido para pri
(como na opção de linha de comando -o pri
), ele se torna 39 - 20 = 19.
Ao usar a opção de linha de comando -l
, ela usa o opri
. Isso significa 20 + 60 = 80.
Então, comparar essas duas linhas de comandos está completamente errado, já que em um caso a prioridade é REVERSA e não a outra. Agora, não me entenda mal ... Eu sei que não há praticamente nada sobre essa informação na documentação de ps
. Cabe a você saber como ps
funciona, eu acho. Felizmente, no Linux, temos o código fonte para o resgate!
Espero que você não precise tornar seu script compatível com um kernel diferente do Linux ...