2013-06-20 14 views
5

私のPython(2.7.3)コードでは、long int(64ビット)を引数として受け入れるioctl呼び出しを使用しようとしています。私は64ビットシステム上にあるので、64ビットintはポインタと同じサイズです。fcntl.ioctl()の64ビット引数

私の問題は、Pythonは、fcntl.ioctl()呼び出しの引数として64ビットintを受け入れていないようです。それはうれしく32ビットのintまたは64ビットのポインタ - を受け入れますが、私が必要とするのは64ビットのintを渡すことです。

ここに私のioctlハンドラがあります:既存のCコードで

static long trivial_driver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 
{ 
    long err = 0; 

    switch (cmd) 
    { 
     case 1234: 
      printk("=== (%u) Driver got arg %lx; arg<<32 is %lx\n", cmd, arg, arg<<32); 
      break; 
     case 5678: 
      printk("=== (%u) Driver got arg %lx\n", cmd, arg); 
      break; 
     default: 
      printk("=== OH NOES!!! %u %lu\n", cmd, arg); 
      err = -EINVAL; 
    } 

    return err; 
} 

、私はこのような呼び出しを使用:Pythonで

static int trivial_ioctl_test(){ 
    int ret; 
    int fd = open(DEV_NAME, O_RDWR); 

    unsigned long arg = 0xffff; 

    ret = ioctl(fd, 1234, arg); // ===(1234) Driver got arg ffff; arg<<32 is ffff00000000 
    arg = arg<<32; 
    ret = ioctl(fd, 5678, arg); // === (5678) Driver got arg ffff00000000 
    close(fd); 

} 

を、私は、デバイスファイルを開き、私が取得します以下の結果:Pythonはメートルを渡すことができます任意の方法は

>>> from fcntl import ioctl 
>>> import os 
>>> fd = os.open (DEV_NAME, os.O_RDWR, 0666) 
>>> ioctl(fd, 1234, 0xffff) 
0 
>>> arg = 0xffff<<32 
>>> # Kernel log: === (1234) Driver got arg ffff; arg<<32 is ffff00000000 
>>> # This demonstrates that ioctl() happily accepts a 32-bit int as an argument. 
>>> import struct 
>>> ioctl(fd, 5678, struct.pack("L",arg)) 
'\x00\x00\x00\x00\xff\xff\x00\x00' 
>>> # Kernel log: === (5678) Driver got arg 7fff9eb1fcb0 
>>> # This demonstrates that ioctl() happily accepts a 64-bit pointer as an argument. 
>>> ioctl(fd, 5678, arg) 

Traceback (most recent call last): 
    File "<pyshell#10>", line 1, in <module> 
    ioctl(fd, 5678, arg) 
OverflowError: signed integer is greater than maximum 
>>> # Kernel log: (no change - OverflowError is within python) 
>>> # Oh no! Can't pass a 64-bit int! 
>>> 

ありますy ioctl()の64ビット引数?

+0

可能であれば、再現可能な例を提供するのに役立ちます。'ioctl()'コールがデバイス固有であることを考えると、実際のリクエストコードに 'IOC_GET_VAL'を代入することで、これをテストするのが難しくなります。 – Aya

+0

@Aya:コメントありがとう。私はデバイス・ドライバーが初めてで、些細でありながら機能的な例を構築するのに少し問題があります。しかし、私は何ができるかを見ていきます。 :) – Ziv

+0

その間、私は 'ctypes'ベースのソリューションを投稿しました。 – Aya

答えて

6

これがPythonのfcntl.ioctl()を使用して可能かどうかは、システムによって異なります。ソースコードをトレース...

# define INT_MAX 2147483647 

を、エラーメッセージが... line 658 of getargs.cに次の試験から

else if (ival > INT_MAX) { 
    PyErr_SetString(PyExc_OverflowError, 
    "signed integer is greater than maximum"); 
    RETURN_ERR_OCCURRED; 
} 

を来ている...と私のシステムで、​​は私に語りました。..それはおそらく(2 ** ((sizeof(int) * 8) - 1)) - 1です。

したがって、sizeof(int)が少なくとも8であるシステムで作業している場合を除き、ctypesモジュールを使用して直接基礎C関数を呼び出す必要がありますが、プラットフォーム固有です。 Linuxでは、このような何かが動作するはずと仮定すると

... Pythonのioctlの '引数' の

from ctypes import * 

libc = CDLL('libc.so.6') 

fd = os.open (DEV_NAME, os.O_RDWR, 0666) 
value = c_uint64(0xffff<<32) 
libc.ioctl(fd, 5678, value) 
+0

はい!これはうまくいきます:) fcntl.ioctl()の内部にはビルトインサポートはありませんが、これは完全に合理的な回避策です。 – Ziv

+0

cf. http://stackoverflow.com/questions/9257065/int-max-in-32-bit-vs-64-bit-environment – Ziv

+0

偉大な答え。あまりにもありがとう:D – Ziv

3

表記は(再び1による)、Pythonで何C.

の異なりますそれはPython整数(32ビットまたは64ビットを指定せずに)、またはバッファオブジェクト(文字列のようなもの)のいずれかです。あなたは実際にはPythonに "ポインタ"を持っていません(32ビットまたは64ビットのアドレスのようなすべての下位アーキテクチャの詳細は完全に隠されています)。

私が必要とするものが実際にはSET_VALが必要な場合は、最初に文字列にstruct.pack(your 64-bit integer)があり、整数を直接渡す代わりにこの文字列をioctlに渡します。あなたは適切に64ビットの整数値を展開する(ではない 'L')再び 'Q' タイプを必要とするGET_VALするため

struct.pack('>Q',1<<32)

:このように

+0

申し訳ありませんが、これは正しくありません。 (申し訳ありませんが、私の元の投稿が十分ではない場合)私が知る限り、** struct.pack()の使用は、cドライバの中でバイナリデータをcのioctlに送るポインタに変換します引数。私はポインタを必要としません。私は渡される64ビットの値を直接制御したい。 – Ziv

+0

厳密に言えば、実際には64ビットの値を32ビットの引数(ポインタまたは '値')で渡すことはできません。また、ioctl呼び出しのパラメータのタイプは、32ビットアーキテクチャで32ビットになります。 64ビットシステムではすべて64ビットになりました。理論的には、C ***の64ビット値をIOCTL **に渡すことができます。 – Georgiy

+0

一方、Pythonはこれらのプラットフォームの特質を隠そうとしているので、ポインタは公開されていません。アイデアは、アーキテクチャが何であるかに決して気を付ける必要はありません。実際にはPythonの整数は任意の大きさにすることができます(つまり、64bitなどで制限されません) _Pythonic_(およびプラットフォームに依存しない)のままにすると、64ビットのような小さなものでもバッファオブジェクトを渡す方が良いでしょう整数... ... – Georgiy