第八章 进程控制:
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
#include <unistd.h>
pid_t fork(void);
ret is -1 means error
child process have a copy-data of parent process
pid_t vfork(void);
ret is -1 means error
child and parent share the data
#include <sys/wait.h>
pid_t wait(int * statloc);
pid_t waitpid(pid_t pid, int * statloc, int option);
if statloc is NULL means we neednot child's exit-status
ret is -1 means error
pid:
== -1, wait any child
> 0, wait child which child-gid == gid
== 0, wait any-child which child-group-id == parent-group-id
< -1, wait any-child which child-group-id == abs(pid)
option:
WCONTINUED, WNOHANG, WUNTRACED
macros of check statloc:
WIFEXITED(status) --> WEXITSTATUS(status)
WIFSIGNALED(status) --> WTERMSIG(status), WCOREDUMP(status)
WIFSTOPPED(status) --> WSTOPSIG(status)
WIFCONTINUED(status)
#include <sys/wait.h> /* only surpport by Solaris */
int waitid(idtype_t idtype, id_t id, siginfo_t * infop, int options);
ret is 0 means success, -1 means error
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
pid_t wait3(int * statloc, int options, struct rusage * ru);
pid_t wait4(pid_t pid, int * statloc, int options, struct rusage * ru);
ret is 0 means success, -1 means error
#include <unistd.h>
int execl(const char * pathname, const char * arg0, ... /* (char *)0 */);
int execv(const char * pathname, char * const argv[]);
int execle(const char * pathname, const char * arg0, ...
/* (char *)0, char * const envp[] */);
int execve(const char * pathname, char * const argv[], char * const envp[]);
int execlp(const char * filename, const char * arg0, ... /* (char *)0 */);
int execvp(const char * filename, char * const argv[]);
if error, return -1; else no return
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
if error return -1, else return 0
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
switch real id and effective id, if one of them is -1, means it not change
if error return -1, else return 0
#include <unistd.h>
int seteuid(uid_t uid);
int setegid(gid_t gid);
if error return -1, else return 0
#include <stdlib.h>
int system(const char * cmdstring);
#include <unistd.h>
char * getlogin(void);
#include <sys/times.h>
clock_t times(struct tms * buf);
if error return -1, else return clock-tik
struct tms {
clock_t tms_utime; /* user CPU time */
clock_t tms_stime; /* system CPU time */
clock_t tms_cutime; /* user CPU time, terminated children */
clock_t tms_cstime; /* system CPU time, terminated children */
};
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int globval = 6;
char buf[] = "a write to stdout\n";
int
main(void)
{
int locaval = 88;
pid_t pid;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) {
printf("write error\n");
exit(-1);
}
fputs("before fork\n", stdout);
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
++globval;
++locaval;
}
else {
sleep(2);
}
printf("pid = %d, globval = %d, locaval = %d\n",
getpid(), globval, locaval);
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int globval = 6;
char buf[] = "a write to stdout\n";
int
main(void)
{
int locaval = 88;
pid_t pid;
fputs("before vfork\n", stdout);
if ((pid = vfork()) < 0) {
printf("vfork error\n");
exit(-1);
}
else if (pid == 0) {
++globval;
++locaval;
_exit(0);
/* if exit/return will fflush/drop the print, or close the stdout */
}
/* parent will wait and continue here */
printf("pid = %d, globval = %d, locaval = %d\n",
getpid(), globval, locaval);
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
void
pr_exit(int status)
{
if (WIFEXITED(status)) {
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
printf("abnormal termination, signal number= %d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)" : "");
#else
"");
#endif
}
else if (WIFSTOPPED(status)) {
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) {
printf("child continued\n");
}
else {
printf("*** unknown status ***\n");
}
}
int
main(void)
{
pid_t pid;
int status;
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
exit(6);
}
if (wait(&status) != pid) {
printf("wait error\n");
exit(-1);
}
pr_exit(status);
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
abort();
}
if (wait(&status) != pid) {
printf("wait error\n");
exit(-1);
}
pr_exit(status);
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
status /= 0;
}
if (wait(&status) != pid) {
printf("wait error\n");
exit(-1);
}
pr_exit(status);
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int
main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid > 0) {
exit(0);
}
/*
* We're the second child; our parent becomes init as soon
* as our real parent calls exit(0) in the statement above.
* Here's where we'd continue executing, knowing that when
* we're done, init will reap our status.
*/
sleep(2);
printf("second child, parent pid = %d\n", getppid());
exit(0);
}
if (waitpid(pid, NULL, 0) != pid) {
printf("waitpid error\n");
exit(-1);
}
/*
* We're the parent (the original process); we continue executing,
* knowing that we're not the parent of the second child.
*/
exit(0);
}
#include <stdio.h>
int
main(int argc, char * argv[])
{
int i;
char ** ptr;
extern char ** environ;
for (i = 0; i < argc; ++i) {
printf("argv[%d]: %s\n", i, argv[i]);
}
for (i = 0, ptr = environ; *ptr != NULL; ++ptr, ++i) {
printf("envp[%d]: %s\n", i, *ptr);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
char * env_init[] = { "USER=unknown", "PATH=/tmp", NULL };
int
main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
if (execle("./8-5.out", "8-5.out", "myarg1",
"MY ARG2", (char *)0, env_init) < 0) {
printf("execle error\n");
}
}
if (waitpid(pid, NULL, 0) != pid) {
printf("waitpid error\n");
exit(-1);
}
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
if (execlp("8-5.out", "8-5.out", "only one arg", NULL) < 0) {
printf("execle error\n");
}
}
if (waitpid(pid, NULL, 0) != pid) {
printf("waitpid error\n");
exit(-1);
}
exit(0);
}
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int
my_system(const char * cmdstring) /*version without signal handling */
{
pid_t pid;
int status;
if (cmdstring == NULL) {
return 1; /* always a command processor with UNIX */
}
if ((pid = fork()) < 0) {
status = -1;
}
else if (pid == 0) {
execl("bin/sh", "sh", "-c", cmdstring, NULL);
_exit(127); /* execl error */
}
else {
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid */
break;
}
}
}
return status;
}
int
main(void)
{
int status;
status = my_system("./8-5.out");
printf("system(./8-5.out): failed - %d\n", status);
status = my_system("sleep 5");
printf("system(sleep 5): failed - %d\n", status);
status = my_system("date");
printf("system(date): failed - %d\n", status);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/times.h>
void
pr_times(clock_t real, struct tms * tmsstart, struct tms * tmsend)
{
static long clktck = 0;
if (clktck == 0) {
if ((clktck = sysconf(_SC_CLK_TCK)) < 0) {
printf("sysconf error\n");
exit(-1);
}
else if (clktck == 0) {
printf("clktck error\n");
exit(-1);
}
}
printf(" real: %7.2f\n", real / (double)clktck);
printf(" user: %7.2f\n",
(tmsend->tms_utime - tmsstart->tms_utime) / (double)clktck);
printf(" sys: %7.2f\n",
(tmsend->tms_stime - tmsstart->tms_stime) / (double)clktck);
printf(" child user: %7.2f\n",
(tmsend->tms_cutime - tmsstart->tms_cutime) / (double)clktck);
printf(" child sys: %7.2f\n",
(tmsend->tms_cstime - tmsstart->tms_cstime) / (double)clktck);
}
void
pr_exit(int status)
{
if (WIFEXITED(status)) {
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
printf("abnormal termination, signal number= %d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)" : "");
#else
"");
#endif
}
else if (WIFSTOPPED(status)) {
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) {
printf("child continued\n");
}
else {
printf("*** unknown status ***\n");
}
}
void
do_cmd(char * cmd)
{
struct tms tmsstart;
struct tms tmsend;
clock_t start;
clock_t end;
int status;
printf("\ncommand: %s\n", cmd);
if ((start = times(&tmsstart)) == -1) {
printf("times error\n");
exit(-1);
}
if ((status = system(cmd)) < 0) {
printf("system error\n");
exit(-1);
}
if ((end = times(&tmsend)) == -1) {
printf("times error\n");
exit(-1);
}
pr_times(end - start, &tmsstart, &tmsend);
pr_exit(status);
}
int
main(int argc, char * argv[])
{
int i;
setbuf(stdout, NULL); /* set stdout to unbuffered */
for (i = 1; i < argc; ++i) {
do_cmd(argv[i]);
}
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#ifdef SOLARIS
#define PSCMD "ps -a -o pid,ppid,s,tty,comm"
#else
#define PSCMD "ps -o pid,ppid,state,tty,command"
#endif
int
main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(-1);
}
else if (pid == 0) {
exit(0);
}
sleep(4);
system(PSCMD);
exit(0);
}