Is there a way to basically call system(), but with a predefined niceness value (20) and low IO priority from Objective-C?

(The low IO priority setting I'm talking about is the one launchd has)

I'm trying to launch /usr/bin/purge from within my Objective-C program.

It would also be ideal for the method to be approved for the Mac App Store.

有帮助吗?

解决方案

Edit: Fork and exec no more, since OSX can't really fork right. Single thread magic:

setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
system("nice -n 20 /usr/bin/purge");
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_DEFAULT);

This can go anywhere, in a dispatch block if you want, or anywhere in your application. No fork in sight. Also, feel free to replace system with NSTask if you want to stay ObjCish.


How about a good old forknexec:

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

And:

if(fork()) {
  /* Set IO priority */
  setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
  /*IO priority is inherited*/
  execl("nice", "-n", "20", "/usr/bin/purge");
}

Let's walk through this:

  • fork: Nothing to see here
  • setiopolicy_np: This is the place where we set IO priority (like launchd). Here are the arguments:

    • IOPOL_TYPE_DISK: We want to limit Disk I/O. There is no other option available anyway.
    • IOPOL_SCOPE_PROCESS: Affects this whole process
    • IOPOL_THROTTLE: This is the policy itself. Accouring to the Apple documentation, it specifies this:

    I/Os with THROTTLE policy are called THROTTLE I/Os. If a THROTTLE I/O request occurs within a small time window (usually a fraction of a second) of another NORMAL I/O request, the thread that issues the THROTTLE I/O is forced to sleep for a certain interval. This slows down the thread that issues the THROTTLE I/O so that NORMAL I/Os can utilize most of the disk I/O bandwidth. Furthermore, a NORMAL I/O request may bypass a previously issued THROTTLE I/O request in kernel or driver queues and be sent to the device first. In some circumstances, very large THROTTLE I/O requests will be broken into smaller requests which are then issued serially.

I/O priority is inherited, and the nice part of the command sets the nice value.

其他提示

A simple way to accomplish this would be using the taskpolicy(8) tool with the -b option:

system("/usr/sbin/taskpolicy -b /usr/bin/purge");

With the -b option taskpolicy uses setpriority(2) to set the background priority(PRIO_DARWIN_BG)

Setting a process to PRIO_DARWIN_BG has this effect on itself and all its children:

"When a thread or process is in a background state the scheduling priority is set to the lowest value, disk IO is throttled (with behavior similar to using setiopolicy_np(3) to set a throttleable policy), and network IO is throttled for any sockets opened after going into background state. Any previously opened sockets ets are not affected."

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top