import ctypes
import fnmatch
import os
import platform
import time
IOPRIO_GET_ARCH_SYSCALL = [
('alpha', '*', 443),
('i*86', '*', 290),
('ia64*', '*', 1275),
('ppc*', '*', 274),
('s390*', '*', 283),
('sparc*', '*', 218),
('sh*', '*', 289),
('x86_64*', '32bit', 290),
('x86_64*', '64bit', 252),
]
IOPRIO_SET_ARCH_SYSCALL = [
('alpha', '*', 442),
('i*86', '*', 289),
('ia64*', '*', 1274),
('ppc*', '*', 273),
('s390*', '*', 282),
('sparc*', '*', 196),
('sh*', '*', 288),
('x86_64*', '32bit', 289),
('x86_64*', '64bit', 251),
]
#查看本机的CPU架构类型和处理器位数
def find_ioprio_syscall_number(syscall_list):
arch = os.uname()[4]
bits = platform.architecture()[0]
for candidate_arch, candidate_bits, syscall_nr in syscall_list:
if fnmatch.fnmatch(arch,candidate_arch) and fnmatch.fnmatch(bits,candidate_bits):
return syscall_nr
class IoprioSetError(Exception):
def __init__(self,err):
try:
self.err = os.strerror(err)
except TypeError:
self.err = err
__NR_ioprio_get = find_ioprio_syscall_number(IOPRIO_GET_ARCH_SYSCALL)
__NR_ioprio_set = find_ioprio_syscall_number(IOPRIO_SET_ARCH_SYSCALL)
#print __NR_ioprio_get,__NR_ioprio_set
try:
ctypes_handle = ctypes.CDLL(None, user_errno=True)
except TypeError:
ctypes_handle = ctypes.CDLL(None)
syscall = ctypes_handle.syscall
#定义几种I/O调度类别
PRIORITY_CLASS = [None, 'rt', 'be', 'idle']
IOPRIO_WHO_PROCESS = 1
IOPRIO_CLASS_SHIFT = 13
IOPRIO_PRIO_MASK = (1 << IOPRIO_CLASS_SHIFT) -1
def ioprio_value(ioprio_class,ioprio_data):
try:
ioprio_class = PRIORITY_CLASS.index(ioprio_class)
except ValueError:
ioprio_class = PRIORITY_CLASS.index(None)
return (ioprio_class << IOPRIO_CLASS_SHIFT) | ioprio_data
def ioprio_class(ioprio):
return PRIORITY_CLASS[ioprio >> IOPRIO_CLASS_SHIFT]
def ioprio_data(ioprio):
return ioprio & IOPRIO_PRIO_MASK
sched_getscheduler = ctypes_handle.sched_getscheduler
SCHED_OTHER, SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_ISO, SCHED_IDLE = range(6)
getpriority = ctypes_handle.getpriority
PRIO_PROCESS = 0
#根据PID获得I/O调度类别和优先级
def get_ioprio_from_sched(pid):
scheduler = sched_getscheduler(pid)
nice = getpriority(PRIO_PROCESS,pid)
ioprio_nice = (nice + 20)/5
if scheduler in (SCHED_FIFO,SCHED_RR):
return 'rt/%d' % ioprio_nice
elif scheduler == SCHED_IDLE:
return 'idle'
else:
return 'be/%d' % ioprio_nice
def get(pid):
if __NR_ioprio_get is None:
return '?sys'
ioprio = syscall(__NR_ioprio_get, IOPRIO_WHO_PROCESS, pid)
if ioprio < 0:
return '?err'
prio_class = ioprio_class(ioprio)
if not prio_class:
return get_ioprio_from_sched(pid)
if prio_class == 'idle':
return prio_class
return '%s/%d' % (prio_class, ioprio_data(ioprio))
def set_ioprio(which, who, ioprio_class, ioprio_data):
if __NR_ioprio_set is None:
raise IoprioSetError('No ioprio_set syscall found')
ioprio_val = ioprio_value(ioprio_class,ioprio_data)
ret = syscall(__NR_ioprio_set, which, who, ioprio_val, use_errno=True)
if ret < 0:
try:
err = ctypes.get_errno()
except AttributeError:
err = 'Unknown error (errno support not available before Python2.6)'
raise IoprioSetError(err)
def sort_key(key):
if key[0] == '?':
return -ord(key[1])
if '/' in key:
if key.startswith('rt/'):
shift = 0
elif key.startswith('be/'):
shift = 1
prio = int(key.split('/')[1])
elif key == 'idle':
shift =2
prio = 0
return (1 << (shift * IOPRIO_CLASS_SHIFT)) + prio
def to_class_and_data(ioprio_str):
if '/' in ioprio_str:
split = ioprio_str.split('/')
return (split[0], int(split[1]))
elif ioprio_str == 'idle':
return ('idle',0)
return (None,None)
#如果指定PID,则获取指定PID的I/O调度类别和优先级,不指定就获取当前进程的I/O调度类别和优先级
if __name__ == '__main__':
import sys
if len(sys.argv) == 2:
pid = int(sys.argv[1])
else:
pid = os.getpid()
print 'pid:', pid
print 'ioprio:', get(pid)
输出结果:
$ python ioprio.py
pid: 11628
ioprio: be/4
$ python ioprio.py 32600
pid: 32600
ioprio: be/4
这个程序涉及到Linux的I/O调度和进程调度的知识
转载于:https://blog.51cto.com/john88wang/1553606