日期:2014-05-16 浏览次数:20858 次
每个进程都有肺腑的整形表示唯一的进程ID。按一个进程终止后,其进程ID就可以再次使用了。如下是几个典型进程的ID及其类型和功能。
ID 进程名 中文名 类型 作用
0 swapper 交换进程 系统进程 它是内核一部分,不执行磁盘上的程序,是调度进程。
1 init init进程 用户进程 永远不会终止,启动系统,读取系统初始化的文件。
2 pagedaemon页精灵进程 系统进程 虚存系统的请页操作
除了进程ID,每个进程还有一些其他的标识符。下列函数返回这些标识符:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); //返回值:调用进程的进程ID
pid_t getppid(void); //返回值:调用进程的父进程ID
uid_t getuid(void); //返回值:调用进程的实际用户ID
uid_t geteuid(void); //返回值:调用进程的有效用户ID
gid_t getgid(void); //返回值:调用进程的实际组ID
gid_t getegid(void); //返回值:调用进程的有效组ID
#include <unistd.h>
pid_t fork(void);
一个现有进程可以调用fork创建一个新进程。
返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1。如下
子进程是父进程的副本。例如:子进程获得父进程数据空间、堆和栈的副本。父子进程不共享这些存储空间部分。父子进程共享正文段。
由于fork之后经常归属exec,所以现在很多实现并不执行一个父进程数据段、栈和堆的完全复制。作为你替代,使用了写时复制(Copy-On-Write)技术。这些区域由父子进程共享,而且内核将他们的访问权限改变为只读的。如果父子进程中的任一个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本。
下面的程序演示了fork函数,从中可以看出子进程对变量所作的改变并不去影响父进程中该变量的值。
#include <unistd.h> #include <stdio.h> int glob = 6; /* externalvariable in initialized data */ char buf[] = "a write to stdout\n"; int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) perror("write error"); printf("before fork\n"); /* we don't flush stdout */ if ((pid = fork()) < 0) { perror("fork error"); }else if (pid == 0) { /* child */ glob++; /* modifyvariables */ var++; }else { sleep(2); /* parent*/ } printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,var); exit(0); }
执行及输出结果:
chen123@ubuntu:~/user/apue.2e$./a.out
awrite to stdout
beforefork
pid= 2755, glob = 7, var = 89
pid= 2754, glob = 6, var = 88
chen123@ubuntu:~/user/apue.2e$./a.out > temp.out