ITPub博客

首页 > IT职业 > IT生活 > 进程控制--进程的其他操作

进程控制--进程的其他操作

原创 IT生活 作者:helloxchen 时间:2010-11-12 14:00:19 0 删除 编辑
一、获得进程ID
系统调用getpid用来获取当前进程的ID。输入命令man 2 getpid可获得该函数的声明:
#include
#include
pid_t getpid(void);
程序7-9是一个使用getpid简单的例子
#include
#include
#include

int main(void)
{
pid_t pid;

if ((pid = fork()) == -1){
printf("fork error!n");
exit(1);
}

if (pid == 0)
printf("getpid return %dn",getpid());
exit(0);
}
运行程序结果如下:
$ ./7-9
getpid return 5590
getpid返回了子进程的ID号5590。
二、setuid和setgid
可以用setuid设置实际用户ID和有效用户ID。与些类似,setgid用来设置实际组ID和有效组ID。函数的声明在unistd.h头文件,声明如下:
#include
#include
int setuid(uid_t uid);
int setgid(gid_t gid);
设置用户ID的setuid函数遵守以下规则(设置组ID的setgid函数与此类似)。
若进程具有root权限,则函数将实际用户ID、有效用户ID设置为参数uid。
若进程不具有root权限,但uid等于实际用户ID,则setuid只将有效用户ID设置为uid,不改变实际用户ID。
若以上两个条件都不能满足,则函数调用失败,返回-1,并设置errno为EPERM。
从以上规则可以看出,只有超级用户进程才能更改实际用户ID。所以一个非特权用户进程是不能通过setuid或setuid得到特权用户权限的。但是su命令却能使一个普通用户变成特权用户。这并不矛盾,因为su是一个“set_uid”程序。执行一个设置了set_uid位的程序时,内核将进程的有效用户ID设置为文件属主的ID。而内核检查一个进程是否具有访问某文件的权限时,是使用进程的有效用户ID来进程检查。su程序的文件属主是root,普通用户运行su命令时,su进程的权限是root权限。
下面通过程序7-10来解释内核是如何检查进程是否有权访问某文件的。可以看到内核是通过检查进程的有效用户ID来检查的,而不是实际用户ID。
#include
#include
#include
#include

extern int errno;

int main()
{
int fd;

printf("uid study:n");
printf("Process's uid = %d,euid = %dn",getuid(),geteuid);

//strerror函数获取指定错误码的提示信息
if ((fd = open("Test.c",O_RDWR)) == -1){
printf("Open failure,errno is %d:%s n",errno,strerror(errno));
exit(1);
}
else{
printf("Open successfully!n");
}

close(fd);
exit(0);
}
以root用户(提示符为#)使用命令在当前目录下创建一个名为Test.c文件:touch Test.c。在root用户下运行该程序,此时文件test.c的权限为-rw-r--r--,即root用户有读写权限,其他用户可读。运行结果为:
# ./7-10
uid study:
Process's uid = 0,euid = 0
Open successfully!
转到另外一个普通用户下,运行结果为:
$ ./7-10
uid study:
Process's uid = 519,euid = 519
Open failure,errno is 13:Permission denied
在root用户下,使用命令chmod对studyuid程序文件设置set_uid位:
# chmod 4755 7-10
然后再换回一个普通用户下,运行结果如下:
$ ./7-10
uid study:
Process's uid = 519,euid = 0
Open successfully!
运行结果说明:内核对进程存取文件的许可权的检查,是通过考查进程的有效用户ID来实现的。
注意:对于调用了setuid函数的程序要格外小心,当进程的有效用户ID即euid是root用户时,如果调用setuid函数使euid为其他非root用户,则该进程从此就不具有超级用户权限了。
可以这样使用setuid函数:开始时某个程序需要root权限完成一些工作,但后续的工作不需要root权限。可以将该可执行程序文件设置set_uid位,并使得该文件的属主是root。这样普通用户执行这个程序时,进程就具有了root权限,当不再需要root权限时,调用setuid(getuid())恢复进程的实际用户ID和有效用户ID为执行该程序的普通用户的ID。对于一些提供网络服务的程序,这样做是非常有必要的,否则就可能被攻击者利用,使攻击控制整个系统。
对于设置了set_uid位的可执行程序也要注意,尤其是对那些属主是root的更要注意。因为Linux系统中root用户拥有最高权力。黑客们往往喜欢寻找设置了set_uid位的可执行程序的漏洞,这样的程序如果存在缓冲区溢出漏洞,并且该程序是一个网络程序,那么黑客可以从远程的地方轻松地利用该漏洞获得运行该漏洞程序的主机的root权限。即使这样的程序不是网络程序,那么也可以使本机上的恶意普通用户提升为root用户。
三、改变进程的优先级
可以通过设置进程的优先级来保证进程优先运行。在Linux下,通过系统调用nice可以改变进程的优先级。nice系统调用用来改变调用进程的优先级。命令行下输入命令man 2 nice可以获得该函数的声明:
#include
int nice(int increment);
在介绍nice系统调用的用法前,需要先了解两个重要的函数:getpriority和setpriority,它们声明如下:
#include
#include
int getpriority(int which,int who);
int setpriority(int which,int who,int prio);
getpriority函数:该函数返回一组进程的优先级。参数which和who组合确定返回哪一组进程的优先级。which的可能取值以及who的意义如下:
PRIO_PROCESS:一个特定的进程,此时who的取值为进程ID。
PRIO_PGRP:一个进程组的所有进程,此时who的取值为进程组ID。
PRIO_USER:一个用户拥有的所有进程,此时参数who取值为实际用户ID。
getpriority函数如果调用成功返回指定进程的优先级,如果出错将返回-1,并设置errno的值。errno可能的取值如下:
ESRCH:which和who的组合与现在的所有进程均不匹配。
EINVAL:which是个无效的值。
注意:当指定的一组进程的优先级不同时,getpriority将返回其中优先级最低的一个。此外,当getpriority返回-1时,可能是发生错误,也有可能是返回的是指定进程的优先级。区分它们的惟一方法是在调用getpriority前将errno清零。如果函数返回-1且errno不为零,说明有错误产生。
setpriority函数:该函数用来设置指定进程的优先级。进程指定的方法与getpriority函数相同。如果调用成功,函数返回指定进程的优先级,出错则返回-1,并设置相应额errno。除了产生与getpriority相同的两个错误外,还有可能产生以下错误。
EPERM:要设置优先级的进程与当前进程不属于同一个用户,并且当前进程没有CAP_SYS_NICE特许。
EACCES:该调用可能降低进程的优先级并且进程没有CAP_SYS_NICE特许。
通过以上两函数,完全可以改变进程的优先级。nice系统调用是它们的一种组合形式,nice系统调用等价于:
int nice(int increment)
{
int oldpro = getpriority(PRIO_PROCESS,getpid());
return setpriority(PRIO_PROCESS,getpid(),oldpro + increment);
}
例7-11演示了nice的使用方法。
#include
#include
#include
#include
#include

int main(void)
{
pid_t pid;
int stat_val = 0;
int oldpri,newpri;

printf("nice studyn");

pid = fork();
switch(pid){
case 0:
printf("Child is running,Curpid is %d,ParentPid is %dn",pid,getpid());
oldpri = getpriority(PRIO_PROCESS,0);
printf("Old priority = %dn",oldpri);
newpri = nice(2);
printf("New priority = %dn",newpri);
exit(0);

case -1:
perror("Process creation failedn");
break;
default:
printf("Parent is running,ChildPid is %d,ParentPid is %dn",pid,getpid());
break;
}
wait(&stat_val);
exit(0);
}
运行结果如下:
$ ./7-11
nice study
Child is running,Curpid is 0,ParentPid is 21428
Old priority = 0
New priority = 2
Parent is running,ChildPid is 21428,ParentPid is 21427
可以看到子进程的优先级由原来的0变为2。
http://blog.chinaunix.net/u2/70445/article_116720.html[@more@]

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/24790158/viewspace-1041372/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 实时调度
请登录后发表评论 登录
全部评论
  • 博文量
    171
  • 访问量
    311104