APUE memo

Chapter. 8 プロセスの制御

fork, exec 系, _exit, wait, waitpid をマスターすれば良い。 レースコンディションについても fork 関数で学べる

プロセスID

getpid/getppid

実ユーザIDと実効ユーザ ID

chmod u+s と実行ファイルにセットユーザIDビットフラグを立てて、 実行すると、そのプロセスのEUIDにファイルのオーナーをセットする。

たとえば、passwdlogin 実行中のプロセスの実効ユーザIDを変えることで、細かな権限処理を行えるようにする at コマンド setuid, seteuid で行うことができる。

fork/vfork

vfork

fork のポイント

man 2 waitpid の NOTES

A child that terminates, but has not been waited for becomes a “zombie”. The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. As long as a zombie process is not removed from the system via a wait, it will consume a slot in the kernel process table, and if this tables fills, it will not be possible to create further processes. If a parent process terminates, them its “zombie” children (if any) are adopt by init(1), which automatically perform a wait to remove zombies

wait/waitpid/waitid

単純化した wait の動作

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char **argv)
{
  printf("ECHILD=%d\n", ECHILD);
  int stat;
  pid_t w = wait(&stat);

  printf("error no=%d\n", errno);
  printf("done: pid=%ld and stat = %d\n", (long) w, stat);

  return 0;
}

違い

exec 関数群

fork で exec するとシェルっぽいことができる。

exec 時オープンしている記述子をどうするかというフラグもある。

exit

setuid/setgid

解釈実行ファイル

関係ないけど chromeos 上の linux の shdash である(Debianベースだからかもしれない)

dash is a POSIX-compliant implementation of /bin/sh that aims to be as small as possible. dash is a direct descendant of the NetBSD version of ash (the Almquist SHell), ported to Linux in early 1997. It was renamed to dash in 2002.

メリット

system

プロセスの実行記録

8.15 ユーザの識別

TODO

プロセススケジューリング

C library/kernel differences Within the kernel, nice values are actually represented using the range 40..1 (since negative numbers are error codes) and these are the values employed by the setpriority() and getpriority() system calls. The glibc wrapper functions for these system calls handle the translations between the user-land and kernel representations of the nice value according to the formula unice = 20 - knice. (Thus, the kernel’s 40..1 range corresponds to the range -20..19 as seen by user space.)

ナイス値の取得/設定

#include <unistd.h>
int nice(int incr);

#include <sys/resource.h>
int getpriority(int which, id_t who);
int setpriority(int which, id_t who);

  1. デフォルトのナイス値を印字
  2. fork する
  3. 子では引数の値でナイス値を変更する
  4. 10秒間カウンタを回し続け、最後に結果を印字

プロセス時間

#include <sys/times.h>
clock_t times(struct tms *buf);

struct tms {
  clock_t tms_utime; /* ユーザCPU時間 */
  clock_t tms_stime; /* システムCPU時間 */
  
  /* 終了した子のCPU時間 */
  clock_t tms_cutime; 
  clock_t tms_cstime;
}

プロセス時間を符号付き32ビット整数として保持し、1秒あたりのティック数を100とした場合、値がオーバーフローするのは何日後か。

演習

8.2

8.6

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  pid_t d = fork();
  char ps_command[100];

  if ( d == -1 ) {
    // no                                                                                                                                           
  } else if ( d == 0 ) {
    _exit(0);
  } else {
    sprintf(ps_command, "ps -ly %ld", (long) d);
    printf("child process id=%ld\n", (long) d);
    system(ps_command);
    sleep(3);
  }

  return 0;
}