fork 函数
pid_t fork(void);
该函数如果执行成功,则会返回两次,对于父进程,返回其子进程的ID,对于子进程,返回0。
![](https://img-my.csdn.net/uploads/201208/08/1344435131_7874.png)
• Real user ID, real groupID, effective user ID, effective group ID
• Supplementary group IDs
• Process group ID
• Session ID
• Controlling terminal
• The set-user-ID andset-group-ID flags
• Current workingdirectory
• Root directory
• File mode creation mask
• Signal mask anddispositions
• The close-on-exec flagfor any open file descriptors
• Environment
• Attached shared memorysegments
• Memory mappings
• Resource limits
exec系列函数
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 []);
实际上,这六个函数只有一个execve属于系统调用,其它都属于库函数的定义,它们之间的关系可见下图:
![](https://img-my.csdn.net/uploads/201208/08/1344435625_8470.png)
进程中的User ID 和 Group ID
int setuid(uid_t uid);
int setgid(gid_t gid);
这两个函数是用来设置进程ID以及组ID的,我们着重介绍setuid函数,后者与其类似,它的执行规则如下:
2. 如果进程没有超级用户的权限,则除非指定ID与real user ID 或则是 saved set-user-ID相同,否则执行不会成功,当执行成功时, effective user ID被设置为指定ID的值。
当我们执行exec系列函数后,如果set user id位已被设置,则进程的 effective user ID将被设置为执行文件的属主ID,而无论该位是否被设置,saved set-user-ID都将被设置为effective user ID的值(这一点非常重要)。
我们来看一下saved set-user-ID的作用,拿man命令来举例,因为它将使用到许多普通用户无法使用的文件,所以它的set user id 是被设置了的,也就是说在执行它的时候,effective user ID将被设置为man用户。然后,由于,我们可以在man运行的过程中通过命令执行其他进程(例如shell),这样是非常危险的,因为它很可能把man的权限传递给危险的进程。为了防止这种情况的发生,man在执行完它的初始化后,在等待用户命令之前,它将调用setuid函数将effective user ID设置回real id(saved set-user-ID不变,依然是man),而在需要再次访问man所需要的文件时,我们再通过setuid提高权限,将effective user ID设置回man(因为saved set-user-ID是man,所以操作合法),所以,我们可以看到man在这里就起着一个记录保存的作用,可以方便安全的进行权限的提高和降低。