【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 进程资源及属性
【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 进程资源及属性
进程资源:
进程资源由两部分组成:内核空间进程资源和用户空间进程资源。
内核空间进程资源即进程控制块(PCB)相关的信息。
包括进程控制块本身、打开的文件表项、当前目录、当前终端信息、线程基本信息、可访问内存地址空间、PID、PPID、UID、EUID等。也就是说,内核通过PCB可以访问到该进程所有的资源。这些资源只能通过系统调用才能访问。这一资源在当前进程退出时,只能由另一进程来回收。
用户空间进程资源包括通过成员mm_struct映射的内存空间。
实质就是进程的代码段、数据段、堆、栈,以及可以共享访问的内存空间。这些资源进程可以直接访问。这些资源在进程退出时主动释放。在进程运行时,可以通过文件/proc/{pid}/maps来查看可以访问的地址空间。
进程状态:
进程基本属性:
与进程本身相关的属性包括进程号(PID)、父进程号(PPID)、进程组号(PGID)。
进程号:获取函数getpid(),在/usr/include/unistd.h中声明。返回值类型为pid_t, 成功返回当前进程的PID,失败返回-1,错误原因存储在error中。pid_t类型其实就是int类型的typedef,重新定义数据类型有助于提高代码的可阅读性。
父进程号:获取函数为getppid(), 成功返回当前进程的父进程号(PPID),其他与getpid()类似。
进程组号:获取函数getpgid(pid_t pid),用来获取指定进程的进程组号(PGID),如果参数为0,表示获取当前进程组号。其他与getpid()类似。也可以用getpgrp()来获取当前进程的进程组号。
系统调用函数setpgid(pid_t pid,pid_t pgid)用来将某进程加入到某个进程组。
会话:是一个或多个进程的集合。getsid(pid_t pid)用来获取某个进程的会话号SID。函数setsid()用来创建新会话。
控制终端:函数tcgetpgrp(int filedes)获取当前前台进程组的进程组号。函数tcsetpgrp(int filedes, pid_t pgrpid)设置某个进程是前台还是后台进程。函数tcgetsid(int filedes)获取控制终端的会话首进程的会话ID。、
示例程序代码(取自《Linux高级程序设计》):
/************************************************************************* > File Name: pg_test.c > Author: Geng > Mail: genglut@163.com > Created Time: Thu 30 Oct 2014 06:16:08 PM CST ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> int main() { int fd; pid_t pid; pid = fork(); if(pid == -1) perror("fork"); else if(pid > 0) { wait(NULL); exit(EXIT_FAILURE); } else { if((fd = open("/dev/pts/0", O_RDWR)) == -1) perror("fopen"); printf("pid=%d, ppid=%d\n", getpid(), getppid()); printf("sid=%d, tcgetsid=%d\n", getsid(getpid()), tcgetsid(fd)); printf("tcgetpgrp=%d\n", tcgetpgrp(fd)); printf("pigd=%d\n", getpgid(getpid())); } }
运行程序:
yang@ubuntu:~/temp$ ps PID TTY TIME CMD 3198 pts/0 00:00:02 bash 4318 pts/0 00:00:00 ps yang@ubuntu:~/temp$ ./pg_test pid=4320, ppid=4319 sid=3198, tcgetsid=3198 tcgetpgrp=4319 pigd=4319
关于进程组、会话和控制终端的文章链接:
http://www.2cto.com/os/201302/191922.html
http://blog.csdn.net/kankan231/article/details/23838711
http://blog.csdn.net/daniel_h1986/article/details/6067685
http://shake863.iteye.com/blog/187085
进程用户属性:
进程真实用户号(RUID) 获取函数:getuid()
真实用户组号(RGID) 获取函数:getgid()
有效用户号(EUID) 获取函数:geteuid()
有效用户组号(EGID) 获取函数:getegid()
其他相关函数:
getresuid(&ruid, &euid, &suid);
getresgid(&rgid, &egid, &sgid);
普通用户能够修改自己的密码的原因:
/etc/passwd文件用来存储所有用户信息,任何用户都可以修改自己的密码,显然,其它用户在执行/usr/bin/passwd命令时修改了/etc/passwd文件(并不是说可以使用vi编辑器修改),但是,通过查看/etc/passwd文件的权限,发现普通用户对此文件仅有读的权限。是什么原因导致普通用户可以修改/etc/passwd文件呢?
这是因为用户执行“/usr/bin/passwd”命令时,/usr/bin/passwd文件设置了setuid位,在执行此程序(/usr/bin/passwd)时,该用户所拥有的权限等同于文件“/usr/bin/passwd”的拥有者root的权限,而root用户拥有对/ect/passwd文件写的权限,因此普通用户可以通过/usr/bin/passwd来修改/etc/passwd文件的内容。
如果清除掉“/usr/bin/passwd”文件的setuid权限位,普通用户就不能修改自己的密码了。
示例代码:
/************************************************************************* > File Name: getid_example.c > Author: Geng > Mail: genglut@163.com > Created Time: Thu 30 Oct 2014 09:33:00 PM CST ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(int argc, char *argv[]) { int pid; printf("\tuid\tgid\teuid\tegid\n"); printf("parent\t%d\t%d\t%d\t%d\n", getuid(), getgid(), geteuid(), getegid()); int ruid, euid, suid; int rgid, egid, sgid; getresuid(&ruid, &euid, &suid); printf("\truid\teuid\tsuid\n"); printf("\t%d\t%d\t%d\n", ruid, euid, suid); getresgid(&rgid, &egid, &sgid); printf("\trgid\tegid\tsgid\n"); printf("\t%d\t%d\t%d\n", rgid, egid, sgid); if((pid = fork()) < 0) { perror("fork"); exit(EXIT_FAILURE); } else if(pid > 0) { sleep(1); } else if(pid == 0) { printf("child\t%d\t%d\t%d\t%d\n", getuid(), getgid(), geteuid(), getegid()); getresuid(&ruid, &euid, &suid); printf("\truid\teuid\tsuid\n"); printf("\t%d\t%d\t%d\n", ruid, euid, suid); getresgid(&rgid, &egid, &sgid); printf("\trgid\tegid\tsgid\n"); printf("\t%d\t%d\t%d\n", rgid, egid, sgid); } return 0; }
关于进程的实际用户ID和有效用户ID的文章链接:
http://www.cnblogs.com/kunhu/p/3699883.html
linux:SUID、SGID详解:
http://www.cnblogs.com/fhefh/archive/2011/09/20/2182155.html
原文链接:http://blog.csdn.net/geng823/article/details/40624497