每个进程都有一个非负整形表示的唯一进程ID。
init进程是一号进程,是第一个用户态的进程。它负责内核启动以后启动一个unix系统,
它读取的配置文件一般在/etc/rc*、/etc/inittab、/etc/init.d中。
下面的函数返回进程的一些标识:
pid_t getpid(void) //调用进程的进程ID.
pid_t getppid(void) //调用进程的父进程。
uid_t getuid(void) //返回调用进程的实际用户ID。
uid_t geteuid(void) //返回用户的有效用户id
uid_t getgid(void) //调用进程的实际用户组ID。
gid_t getegid(void) //调用进程的实际组ID。
8.3fork函数
#include "apue.h"
int glob = 6;
char buf[] = "a write to stdout\n";
int main(void)
{
int var;
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf) - 1) != sizeof(buf) - 1)
err_sys("write error");
printf("before fork\n");
if ((pid = fork()) < 0)
{
err_sys("fork error");
}else if (pid == 0)
{
glob++;
var++;
}else
{sleep(2);
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
exit(0);
}
[root@localhost apue]# ./a.out
a write to stdout
before fork
pid = 7656, glob = 7, var = 89
pid = 7655, glob = 6, var = 88
[root@localhost apue]# ./a.out >fort.out
[root@localhost apue]# cat fort.out
a write to stdout
before fork
pid = 7671, glob = 7, var = 89
before fork
pid = 7670, glob = 6, var = 88
父进程和子进程共享打开的文件。子进程把父进程的所有打开的文件描述符都复制到子进程中。
8.4vfork函数
#include "apue.h"
int glob = 6;
int main()
{
int var;
pid_t pid;
var = 88;
printf("before vfork\n");
if ((pid = vfork()) < 0){
err_sys("vfork error");
}else if (pid == 0){
glob++;
var++;
_exit(0);
}
printf("pid = %d, glob = %d, var = %d\n", getpid, glob, var);
exit(0);
}
[root@localhost apue]# vim vforktest.c
[root@localhost apue]# gcc vforktest.c
[root@localhost apue]# ./a.out
before vfork
pid = 134513812, glob = 7, var = 89
8.6wait和waitpid函数
#include "apue.h"
#include <sys/wait.h>
void pr_exit(int status);
int main(void)
{
pid_t pid;
int status;
if ((pid = fork()) < 0)
err_sys("error fork");
else if (pid == 0)
exit(7);
if (wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
if ((pid = fork()) < 0)
err_sys("error fork");
else if (pid == 0)
abort();
if (wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
if ((pid = fork()) < 0)
err_sys("error fork");
else if (pid == 0)
status /= 0;
if (wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
exit(0);
}
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));
}
[root@localhost apue]# vim exittest.c
[root@localhost apue]# gcc exittest.c
exittest.c: In function ‘main’:
exittest.c:28: 警告:被零除
[root@localhost apue]# ./a.out
normal termination,exit status = 7
abnormal termination, signal number = 6
abnormal termination, signal number = 8
如果一个进程有几个子进程,name只要有一个子进程终止,wait函数就返回。
#include "apue.h"
#include <sys/wait.h>
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
{
err_sys("fork error");
}else if (pid == 0)
{
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid > 0)
exit(0);
sleep(2);
printf("second child, parent pid =%d\n", getppid());
exit(0);
}
if (waitpid(pid, NULL, 0) != pid)
err_sys("waitpid error");
exit(0);
}
[root@localhost apue]# ./a.out >wait.test
[root@localhost apue]# cat wait.test
second child, parent pid =1
8.7waitid函数
8.9竞争条件
#include "apue.h" TELL_WAIT(); /* set things up for TELL_xxx & WAIT_xxx */ if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { /* child */ /* child does whatever is necessary ... */ TELL_PARENT(getppid()); /* tell parent we're done */ WAIT_PARENT(); /* and wait for parent */ /* and the child continues on its way ... */ exit(0); } /* parent does whatever is necessary ... */ TELL_CHILD(pid); /* tell child we're done */ WAIT_CHILD(); /* and wait for child */ /* and the parent continues on its way ... */ exit(0);
#include "apue.h"
static void charatatime(char *);
int main()
{
pid_t pid;
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0)
charatatime("output from chlid\n");
else
charatatime("output from parent\n");
exit(0);
}
static void charatatime(char *str)
{
char *ptr;
int c;
setbuf(stdout,NULL);
for (ptr = str; (c = *ptr++) != 0;)
putc(c, stdout);
}
[root@localhost apue]# vim choicetest.c
[root@localhost apue]# gcc choicetest.c
[root@localhost apue]# ./a.out
output from chlid
output from parent
[root@localhost apue]# ./a.out
output from chlid
output from parent
8.10exec函数
exec并不创建新进程,只是一个全新的程序替换了当前进程的正文、数据、堆、栈。#include "apue.h"
#include <sys/wait.h>
char *env_init[] = {"USER=unknown", "PATH=/tmp", NULL};
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0)
{
if (execle("/home/huangcd/echoall", "echoall", "myarg1", "MY ARG2", (char *)0, env_init) < 0)
err_sys("execle error");
}
if (waitpid(pid, NULL, 0) < 0)
err_sys("execle error");
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0)
{
if (execlp("echoall", "echoall", "only 1 arg", (char *)0) < 0)
err_sys("execlp error");
}
exit(0);
}
8.11更改用户ID和组ID
unix对文件权限的管理师基于用户和组ID的。8.13system函数
#include "apue.h"
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
int system(const char *cmdstring);
void pr_exit(int status);
int main(void)
{
int status;
if ((status = system("date")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("nosuckcommand")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("who; exit 44")) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
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));
}
int system(const char *cmdstring)
{
pid_t pid;
int status;
if (cmdstring == NULL)
return(1);
if ((pid = fork()) < 0)
{
status = -1;
}else if (pid ==0)
{
execl("/bin/bash", "sh", "-c", cmdstring, (char *)0);
_exit(127);
}else{
while (waitpid(pid, &status, 0) < 0){
if (errno != EINTR){
status = -1;
break;
}
}
}
return(status);
}
[root@localhost apue]# vim systemtest.c
[root@localhost apue]# gcc systemtest.c
[root@localhost apue]# ./a
a.out apue.h
[root@localhost apue]# ./a.out
2014年 01月 04日 星期六 01:05:36 CST
normal termination,exit status = 0
sh: nosuckcommand: command not found
normal termination,exit status = 127
root :0 2014-01-03 18:07
root pts/1 2014-01-03 18:13 (:0.0)
normal termination,exit status = 44
我们可以通过下面的函数来得到登陆的用户名:
char * getlogin(void)
我们通过调用此函数的进程来得到实际用户的登录名。
8.16进程时间
struct tms{
#include "apue.h"
#include <sys/wait.h>
#include <sys/times.h>
void pr_exit(int);
static void do_cmd(char *);
static void pr_times(clock_t, struct tms *, struct tms *);
int main(int argc, char *argv[])
{
int i;
setbuf(stdout, NULL);
for (i = 1; i < argc; i++)
do_cmd(argv[i]);
exit(0);
}
static void do_cmd(char *cmd)
{
struct tms tmsstart,tmsend;
clock_t start,end;
int status;
printf("\ncommand:%s\n",cmd);
if ((start = times(&tmsstart)) == -1)
err_sys("times error");
if ((status = system(cmd)) < 0)
err_sys("system() error");
if ((end = times(&tmsend)) < 0)
err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
pr_exit(status);
}
static 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)
err_sys("sysconf error");
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));
}
[root@localhost apue]# ./a.out "sleep 5" "date"
command:sleep 5
real: 5.00
user: 0.00
sys: 0.00
child user: 0.00
child sys: 0.00
normal termination,exit status = 0
command:date
2014年 01月 04日 星期六 11:48:50 CST
real: 0.01
user: 0.00
sys: 0.00
child user: 0.00
child sys: 0.00
normal termination,exit status = 0