2011-04-17 81 views
3

我有一个类似守护程序的应用程序,它在初始化时执行了一些磁盘密集型处理。为了避免减缓其他任务我做这样的事情在Windows上:在Linux上相当于SetPriorityClass

SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN); 

// initialization tasks 

SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END); 

// daemon is ready and running at normal priority 

据我所知,在Unix系统可致电我漂亮或setpriority并降低进程的优先级,但我不能提高它回到它是在过程创建(即没有等同于第二个SetPriorityClass调用),除非我拥有超级用户权限。有没有机会以另一种方式去做我失踪的事情? (我知道我可以创建一个运行在低优先级的线程初始化,并等待它在主线程上完成的,但我宁愿宁愿回避的态度)

编辑:积分为等效SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);

回答

5

你说你处理磁盘密集型,所以使用nice解决方案将无法正常工作。 nice处理CPU访问的优先级,而不是I/O访问。 PROCESS_MODE_BACKGROUND_BEGIN降低I/O优先级以及CPU优先级,并且需要XP和更早版本中不存在的内核功能。

控制I/O优先级是不能跨越Unix系统移植,但对现代Linux内核的解决方案。你需要CAP_SYS_ADMIN降低I/O优先IO_PRIO_CLASS_IDLE,但有可能降低,提高尽力而为类中的优先级没有这个。

的关键函数调用是ioprio_set,你必须通过一个syscall包装致电:

static int ioprio_set(int which, int who, int ioprio) 
{ 
    return syscall(SYS_ioprio_set, which, who, ioprio); 
} 

对于完整的示例源,see here

根据权限的不同,您进入后台模式为IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_IDLE,0)IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,7)。然后,顺序应该是:

#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) 

ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,7)); 
// Do work 
ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,4)); 

注意你很多没有被允许返回到原来的IO优先级,所以你需要返回到另一个尽力而为值。

+0

Unices - 我喜欢它。 – 2011-04-22 16:28:58

3

实际上,如果你有一个合理的近期的内核,那么可能会有一个解决方案。下面是TLPI这样说:

在Linux内核2.6.12之前,一个 非特权过程可以使用 setpriority()可只(不可逆) 降低其自身或其他进程的 nice值。

由于内核2.6.12,Linux提供 的RLIMIT_NICE资源限制,这 允许非特权进程 增加nice值。非特权的 过程可以将其自己的好值 提高到由公式20-rlim_cur指定的最大值,其中rlim_cur 是当前的RLIMIT_NICE软 资源限制。

所以基本上你必须:

  1. 使用ulimit -e设置RLIMIT_NICE
  2. 使用setpriority像往常一样

下面是一个例子

编辑/etc/security/limits.conf。添加

cnicutar - nice -10 

验证使用的ulimit

[email protected]:~$ ulimit -e 
30 

我们喜欢这样的限制,所以我们不改变它。

好的LS

[email protected]:~$ nice -n -10 ls tmp 
[email protected]:~$ 

[email protected]:~$ nice -n -11 ls tmp 
nice: cannot set niceness: Permission denied 

setpriority例如

#include <stdio.h> 
#include <sys/resource.h> 
#include <unistd.h> 

int main() 
{ 
     int rc; 

     printf("We are being nice!\n"); 
     /* set our nice to 10 */ 
     rc = setpriority(PRIO_PROCESS, 0, 10); 
     if (0 != rc) { 
       perror("setpriority"); 
     } 

     sleep(1); 

     printf("Stop being nice\n"); 
     /* set our nice to -10 */ 
     rc = setpriority(PRIO_PROCESS, 0, -10); 
     if (0 != rc) { 
       perror("setpriority"); 
     } 

     return 0; 
} 

测试程序

[email protected]:~$ ./nnice 
We are being nice! 
Stop being nice 
[email protected]:~$ 

唯一的缺点是,它不是移植到其他Unix系统(或者是Unix系统?)。

0

要workaroud降低优先级,然后带回来,您可以:

  1. 叉()
  2. 子:降低其优先
  3. 家长:等待子(保持原父母的优先级)
  4. 子:做的工作(在低优先级)
  5. 家长:继续使用原有优先的孩子完成之后。

这应该是UNIX的便携式解决方案。

+1

从问题:“(我知道我可以创建一个初始化线程以低优先级运行,并等待它在主线程上完成,但我宁愿避免它)” – CAFxX 2011-04-19 16:06:42