SlideShare a Scribd company logo
用 Python 和硬體溝通一下 !
Taipei.py Sep. 2018
About the speaker
kaif@kaif.io
● (infra|storage) 打雜工
● mogilefs-moji member
● Py@home, Java@workspace
● ...
Outline in the bottom-up perspective
Device
Device driver
ioctl
Your python app here!
Device
本日裝置擔當 =>
Operating tape device
讀寫檔案步驟
● 將磁帶放入tape library
● 以機械手臂將指定磁帶放到tape drive
● 驅動磁帶轉至要讀寫的位置 <= 今天要示範控制的部分!
● 開始讀寫
Tape drive actions
● status - Print status information about the tape unit.
● rewind - Rewind the tape.
Driver
Drivers (device file) in linux
Drivers for tape devices
● sg - Linux SCSI generic (sg) driver
● st - Linux SCSI tape (st) device driver
ioctl()
ioctl overview
● first appeared in Unix v7 (1979)
● a system call for input/output control
○ user space <== system call ==> kernel space
○ user code <== ioctl ==> driver
● carrys message which contains:
○ file descriptor
○ type (8 bits, a~z)
○ number (8 bits, 1~255)
○ argument size (14 bits, max 16KB)
○ direction (2 bits, R/W/RW/NONE)
○ argument (C struct in typical)
It’s just like your RESTful API call in the old school style!
Concept mapping between client-server and user space -kernel
space
It’s just like your RESTful API call in the old school style!
Concept mapping between ioctl message and restful API
PUT /myBucket/my-object.jpg HTTP/1.1
Host: s3.amazonaws.com
Date: Wed, 12 Oct 2009 17:50:00 GMT
Authorization: authorization string
Content-Type: text/plain
Content-Length: 11434
x-amz-meta-author: Janet
Expect: 100-continue
[11434 bytes of object data]
file descriptor
direction type number
argument size
arguments
ioctl() in standard C library
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
file descriptor
arguments
IOC (direction, type,
number, argument size)
ioctl() from Python
We are Pythonista!
There are at least three kinds of ways to do ioctl() from python:
● cpython extension
● ctypes — A foreign function library for Python
● fcntl — The fcntl and ioctl system call
● ...
We are Pythonista!
Assume we will like to call the python functions which are look like:
● mt.rewind(/dev/nst0)
● mt.status(/dev/nst0)
Approach 1: cpython extension
1. Define functions
1a. Parse input from PyObject to C
types
1b. Write down C procedure as usual
way
1c. Convert result back to a PyObject
static PyObject * do_status(PyObject *self, PyObject *args) {
// parse input
const char *device;
if (!PyArg_ParseTuple(args, "s", &device))
return NULL;
// open device file
int fd;
if ((fd = open(device, O_RDONLY)) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
// execute ioctl command
struct mtget status;
if (ioctl(fd, MTIOCGET, (char *)&status) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if (status.mt_type != MT_ISSCSI2) {
PyErr_SetString(PyExc_NotImplementedError, "Unsupported tape
type");
return NULL;
}
close(fd);
// return status info in dict
return Py_BuildValue("{s:i,s:i,s:i}",
"file number", status.mt_fileno,
"block number", status.mt_blkno,
"partition", (status.mt_resid & 0xff)
);
}
2. Module metadata
2a. init function
2b. module definition
2c. function/method lookup table
PyMODINIT_FUNC PyInit_mt(void) {
PyObject* m = PyModule_Create(&mtmodule);
if (m == NULL) {
return NULL;
}
return m;
}
static struct PyModuleDef mtmodule = {
PyModuleDef_HEAD_INIT,
"mt", /* name of module */
NULL, /* module documentation, may be NULL */
-1,
MtMethods
};
static PyMethodDef MtMethods[] = {
{"rewind", do_rewind, METH_VARARGS,
"Rewind the tape."},
{"status", do_status, METH_VARARGS,
"Print status information about the tape unit."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
Approach 2: ctypes
1. Load C library
Load glibc by ctypes. We will call ioctl()
from this later
def _get_ioctl_fn():
global _ioctl_fn
if _ioctl_fn is not None:
return _ioctl_fn
libc_name = ctypes.util.find_library('c')
if not libc_name:
raise Exception('Unable to find c library')
libc = ctypes.CDLL(libc_name, use_errno=True)
_ioctl_fn = libc.ioctl
return _ioctl_fn
2. Define data
structure
Define input/output/buffer data
structure by extending
ctypes.Structure
class mtop(ctypes.Structure):
_fields_ = [
("mt_op", ctypes.c_short),
("mt_count", ctypes.c_int)
]
class mtget(ctypes.Structure):
_fields_ = [
("mt_type", ctypes.c_long),
("mt_resid", ctypes.c_long),
("mt_dsreg", ctypes.c_long),
("mt_gstat", ctypes.c_long),
("mt_erreg", ctypes.c_long),
("mt_fileno", ctypes.c_int),
("mt_blkno", ctypes.c_int),
]
def rewind(device):
MTIOCTOP = ioctl.linux.IOW('m', 1, ctypes.sizeof(mtop))
MTREW = 6
mt_com = mtop(MTREW, 1)
with open(device, 'r') as fd:
ioctl.ioctl(fd.fileno(), MTIOCTOP,
ctypes.byref(mt_com))
def status(device):
// plz ref it in github
Last one: fcntl
1. Porting
You needs to do porting job from C to
python since fcntl does not provide any
help on this...orz
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_DIRBITS = 2
_IOC_NRMASK = (1 << _IOC_NRBITS) - 1
_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1
_IOC_NRSHIFT = 0
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
IOC_NONE = 0
IOC_WRITE = 1
IOC_READ = 2
def IOC(dir, type, nr, size):
assert dir <= _IOC_DIRMASK, dir
assert type <= _IOC_TYPEMASK, type
assert nr <= _IOC_NRMASK, nr
assert size <= _IOC_SIZEMASK, size
return (dir << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) |
(size << _IOC_SIZESHIFT)
def IOC_SIZECHECK(t):
result = t
assert result <= _IOC_SIZEMASK, result
return result
def IOW(type, nr, size):
return IOC(IOC_WRITE, type, nr, IOC_SIZECHECK(size))
def IOR(type, nr, size):
return IOC(IOC_READ, type, nr, IOC_SIZECHECK(size))
2. input/output
conversion
Convert function input/output back and
forth. struct.pack() and
struct.unpack() are your friends
here.
def rewind(device):
MTREW = 6
mt_com = struct.pack('hi', MTREW, 1)
MTIOCTOP = IOW(ord('m'), 1, len(mt_com))
with open(device, 'r') as fd:
fcntl.ioctl(fd, MTIOCTOP, mt_com)
def status(device):
long_size = 8
int_size = 4
status = bytearray(long_size * 5 + int_size * 2)
MTIOCGET = IOR(ord('m'), 2, len(status))
with open(device, 'r') as fd:
fcntl.ioctl(fd, MTIOCGET, status)
status = struct.unpack('lllllii', status)
return {
"file number": status[-2],
"block number": status[-1],
"partition": status[1] & 0xff
}
3. Iusse ioctl()
via fcntl.ioctl(), this is actually the
only thing fcntl can do....
def rewind(device):
MTREW = 6
mt_com = struct.pack('hi', MTREW, 1)
MTIOCTOP = IOW(ord('m'), 1, len(mt_com))
with open(device, 'r') as fd:
fcntl.ioctl(fd, MTIOCTOP, mt_com)
def status(device):
long_size = 8
int_size = 4
status = bytearray(long_size * 5 + int_size * 2)
MTIOCGET = IOR(ord('m'), 2, len(status))
with open(device, 'r') as fd:
fcntl.ioctl(fd, MTIOCGET, status)
status = struct.unpack('lllllii', status)
return {
"file number": status[-2],
"block number": status[-1],
"partition": status[1] & 0xff
}
Comparision
Pros Cons
cpython extension 最大的控制權
CPython only,要會一
點C
ctypes 功能強大、跨平台
複雜,擁有三者中篇幅
最大的文件
fcntl
毫無反應,就只是提供
ioctl()
毫無反應,就只是提供
ioctl()
Recap
● Understand your device
● Read driver’s document
● Drive you driver via ioctl()
● Binding it in Python
Example code is available on
https://github.com/hrchu/playioctl
Speaker is available!? on
https://medium.com/@petertc

More Related Content

PPTX
gestion de carnet d'adresses en Java
PPS
5. muradif, musytarak, mantuq, mafhum, zahir, muawwal
PDF
Juju/MAASで作る Kubernetes + GPU
PDF
CRC-32
PPTX
Zakat profesi
PDF
Cpu pipeline basics
PPTX
Kelompok 1 teknik khitobah
gestion de carnet d'adresses en Java
5. muradif, musytarak, mantuq, mafhum, zahir, muawwal
Juju/MAASで作る Kubernetes + GPU
CRC-32
Zakat profesi
Cpu pipeline basics
Kelompok 1 teknik khitobah

What's hot (20)

PPTX
Syirkah
PDF
OSC2011 Tokyo/Spring 自宅SAN友の会(前半)
PPTX
[오픈소스컨설팅] Linux Network Troubleshooting
PDF
痛い目にあってわかる HAクラスタのありがたさ
PDF
FPGA+SoC+Linux実践勉強会資料
PDF
あるmmapの話
PPT
cupdf.com_kaidah-fikih.ppt
PDF
Decoupling Compute from Memory, Storage and IO with OMI
PDF
UM2019 Extended BPF: A New Type of Software
ODP
eBPF maps 101
PPT
PPS
1. qawa'id pengertian & ruang lingkup
PDF
Linux packet-forwarding
PDF
Ultra96ボードでYOLOを高速化
PDF
ここまできた! ”第6世代”ファイバーチャネルがもたらす ストレージ・ネットワークの 新たな可能性とは?
PDF
Docker infiniband
PDF
How NOT to Write a Microbenchmark
PDF
『コンテナ疲れ』と戦う、k8s・PaaS・Serverlessの活用法
PPTX
PostgreSQL and Linux Containers
PPS
8. al umuru bi maqashidiha, al-yaqinu
Syirkah
OSC2011 Tokyo/Spring 自宅SAN友の会(前半)
[오픈소스컨설팅] Linux Network Troubleshooting
痛い目にあってわかる HAクラスタのありがたさ
FPGA+SoC+Linux実践勉強会資料
あるmmapの話
cupdf.com_kaidah-fikih.ppt
Decoupling Compute from Memory, Storage and IO with OMI
UM2019 Extended BPF: A New Type of Software
eBPF maps 101
1. qawa'id pengertian & ruang lingkup
Linux packet-forwarding
Ultra96ボードでYOLOを高速化
ここまできた! ”第6世代”ファイバーチャネルがもたらす ストレージ・ネットワークの 新たな可能性とは?
Docker infiniband
How NOT to Write a Microbenchmark
『コンテナ疲れ』と戦う、k8s・PaaS・Serverlessの活用法
PostgreSQL and Linux Containers
8. al umuru bi maqashidiha, al-yaqinu
Ad

Similar to Taipei.py 2018 - Control device via ioctl from Python (20)

PDF
EuroPython 2020 - Speak python with devices
PDF
Getting Started with Embedded Python: MicroPython and CircuitPython
PDF
PyCon_India_2017_MicroPython_Ayan
PDF
Zn task - defcon russia 20
PDF
IoT: Internet of Things with Python
PDF
Iot Bootcamp - abridged - part 1
ODP
MicroPython&electronics prezentācija
PPT
AUTOMATED TESTING USING PYTHON (ATE)
PDF
Interfacing C++ with Python to boost your legacy apps with Python interfaces
PPTX
Python-in-Embedded-systems.pptx
PDF
Lost in Translation: When Industrial Protocol Translation goes Wrong [CONFide...
PDF
Cluj.py Meetup: Extending Python in C
PDF
MicroPython Introduction PUSG July 2017
PDF
Getting Started with MicroPython and LoPy
PDF
Python in the real world : from everyday applications to advanced robotics
PDF
Hardware hacking
PDF
Cython - close to metal Python
PDF
Iot bootcamp abridged - part 2
PDF
Tangible Tools For Teaching With Python
PDF
Internet of Energy: "Can python prevent California wildfires?"
EuroPython 2020 - Speak python with devices
Getting Started with Embedded Python: MicroPython and CircuitPython
PyCon_India_2017_MicroPython_Ayan
Zn task - defcon russia 20
IoT: Internet of Things with Python
Iot Bootcamp - abridged - part 1
MicroPython&electronics prezentācija
AUTOMATED TESTING USING PYTHON (ATE)
Interfacing C++ with Python to boost your legacy apps with Python interfaces
Python-in-Embedded-systems.pptx
Lost in Translation: When Industrial Protocol Translation goes Wrong [CONFide...
Cluj.py Meetup: Extending Python in C
MicroPython Introduction PUSG July 2017
Getting Started with MicroPython and LoPy
Python in the real world : from everyday applications to advanced robotics
Hardware hacking
Cython - close to metal Python
Iot bootcamp abridged - part 2
Tangible Tools For Teaching With Python
Internet of Energy: "Can python prevent California wildfires?"
Ad

More from Hua Chu (8)

PDF
CYBERSEC2025 - 生成式 AI 合規技術與挑戰 / Gen AI: Risks and Compliance Strategies
PDF
COSCUP2024 - SCaLE:打開北美開源世界的大門 / Insights from SCaLE and Beyond
PDF
PyConline AU 2021 - Things might go wrong in a data-intensive application
PDF
PyCon HK 2018 - Heterogeneous job processing with Apache Kafka
PDF
TANET 2018 - Insights into the reliability of open-source distributed file sy...
PPTX
Apache spot 系統架構
PPTX
Apache spot 初步瞭解
PDF
TWJUG 2016 - Mogilefs, 簡約可靠的儲存方案
CYBERSEC2025 - 生成式 AI 合規技術與挑戰 / Gen AI: Risks and Compliance Strategies
COSCUP2024 - SCaLE:打開北美開源世界的大門 / Insights from SCaLE and Beyond
PyConline AU 2021 - Things might go wrong in a data-intensive application
PyCon HK 2018 - Heterogeneous job processing with Apache Kafka
TANET 2018 - Insights into the reliability of open-source distributed file sy...
Apache spot 系統架構
Apache spot 初步瞭解
TWJUG 2016 - Mogilefs, 簡約可靠的儲存方案

Recently uploaded (20)

PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Nekopoi APK 2025 free lastest update
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
top salesforce developer skills in 2025.pdf
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
PTS Company Brochure 2025 (1).pdf.......
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Odoo POS Development Services by CandidRoot Solutions
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
How to Migrate SBCGlobal Email to Yahoo Easily
Nekopoi APK 2025 free lastest update
How to Choose the Right IT Partner for Your Business in Malaysia
Design an Analysis of Algorithms I-SECS-1021-03
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Which alternative to Crystal Reports is best for small or large businesses.pdf
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
Reimagine Home Health with the Power of Agentic AI​
Softaken Excel to vCard Converter Software.pdf
top salesforce developer skills in 2025.pdf
2025 Textile ERP Trends: SAP, Odoo & Oracle
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PTS Company Brochure 2025 (1).pdf.......

Taipei.py 2018 - Control device via ioctl from Python

  • 1. 用 Python 和硬體溝通一下 ! Taipei.py Sep. 2018
  • 2. About the speaker kaif@kaif.io ● (infra|storage) 打雜工 ● mogilefs-moji member ● Py@home, Java@workspace ● ...
  • 3. Outline in the bottom-up perspective Device Device driver ioctl Your python app here!
  • 6. Operating tape device 讀寫檔案步驟 ● 將磁帶放入tape library ● 以機械手臂將指定磁帶放到tape drive ● 驅動磁帶轉至要讀寫的位置 <= 今天要示範控制的部分! ● 開始讀寫
  • 7. Tape drive actions ● status - Print status information about the tape unit. ● rewind - Rewind the tape.
  • 10. Drivers for tape devices ● sg - Linux SCSI generic (sg) driver ● st - Linux SCSI tape (st) device driver
  • 12. ioctl overview ● first appeared in Unix v7 (1979) ● a system call for input/output control ○ user space <== system call ==> kernel space ○ user code <== ioctl ==> driver ● carrys message which contains: ○ file descriptor ○ type (8 bits, a~z) ○ number (8 bits, 1~255) ○ argument size (14 bits, max 16KB) ○ direction (2 bits, R/W/RW/NONE) ○ argument (C struct in typical)
  • 13. It’s just like your RESTful API call in the old school style! Concept mapping between client-server and user space -kernel space
  • 14. It’s just like your RESTful API call in the old school style! Concept mapping between ioctl message and restful API PUT /myBucket/my-object.jpg HTTP/1.1 Host: s3.amazonaws.com Date: Wed, 12 Oct 2009 17:50:00 GMT Authorization: authorization string Content-Type: text/plain Content-Length: 11434 x-amz-meta-author: Janet Expect: 100-continue [11434 bytes of object data] file descriptor direction type number argument size arguments
  • 15. ioctl() in standard C library #include <sys/ioctl.h> int ioctl(int fd, unsigned long request, ...); file descriptor arguments IOC (direction, type, number, argument size)
  • 17. We are Pythonista! There are at least three kinds of ways to do ioctl() from python: ● cpython extension ● ctypes — A foreign function library for Python ● fcntl — The fcntl and ioctl system call ● ...
  • 18. We are Pythonista! Assume we will like to call the python functions which are look like: ● mt.rewind(/dev/nst0) ● mt.status(/dev/nst0)
  • 19. Approach 1: cpython extension
  • 20. 1. Define functions 1a. Parse input from PyObject to C types 1b. Write down C procedure as usual way 1c. Convert result back to a PyObject static PyObject * do_status(PyObject *self, PyObject *args) { // parse input const char *device; if (!PyArg_ParseTuple(args, "s", &device)) return NULL; // open device file int fd; if ((fd = open(device, O_RDONLY)) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } // execute ioctl command struct mtget status; if (ioctl(fd, MTIOCGET, (char *)&status) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } if (status.mt_type != MT_ISSCSI2) { PyErr_SetString(PyExc_NotImplementedError, "Unsupported tape type"); return NULL; } close(fd); // return status info in dict return Py_BuildValue("{s:i,s:i,s:i}", "file number", status.mt_fileno, "block number", status.mt_blkno, "partition", (status.mt_resid & 0xff) ); }
  • 21. 2. Module metadata 2a. init function 2b. module definition 2c. function/method lookup table PyMODINIT_FUNC PyInit_mt(void) { PyObject* m = PyModule_Create(&mtmodule); if (m == NULL) { return NULL; } return m; } static struct PyModuleDef mtmodule = { PyModuleDef_HEAD_INIT, "mt", /* name of module */ NULL, /* module documentation, may be NULL */ -1, MtMethods }; static PyMethodDef MtMethods[] = { {"rewind", do_rewind, METH_VARARGS, "Rewind the tape."}, {"status", do_status, METH_VARARGS, "Print status information about the tape unit."}, {NULL, NULL, 0, NULL} /* Sentinel */ };
  • 23. 1. Load C library Load glibc by ctypes. We will call ioctl() from this later def _get_ioctl_fn(): global _ioctl_fn if _ioctl_fn is not None: return _ioctl_fn libc_name = ctypes.util.find_library('c') if not libc_name: raise Exception('Unable to find c library') libc = ctypes.CDLL(libc_name, use_errno=True) _ioctl_fn = libc.ioctl return _ioctl_fn
  • 24. 2. Define data structure Define input/output/buffer data structure by extending ctypes.Structure class mtop(ctypes.Structure): _fields_ = [ ("mt_op", ctypes.c_short), ("mt_count", ctypes.c_int) ] class mtget(ctypes.Structure): _fields_ = [ ("mt_type", ctypes.c_long), ("mt_resid", ctypes.c_long), ("mt_dsreg", ctypes.c_long), ("mt_gstat", ctypes.c_long), ("mt_erreg", ctypes.c_long), ("mt_fileno", ctypes.c_int), ("mt_blkno", ctypes.c_int), ] def rewind(device): MTIOCTOP = ioctl.linux.IOW('m', 1, ctypes.sizeof(mtop)) MTREW = 6 mt_com = mtop(MTREW, 1) with open(device, 'r') as fd: ioctl.ioctl(fd.fileno(), MTIOCTOP, ctypes.byref(mt_com)) def status(device): // plz ref it in github
  • 26. 1. Porting You needs to do porting job from C to python since fcntl does not provide any help on this...orz _IOC_NRBITS = 8 _IOC_TYPEBITS = 8 _IOC_SIZEBITS = 14 _IOC_DIRBITS = 2 _IOC_NRMASK = (1 << _IOC_NRBITS) - 1 _IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1 _IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1 _IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1 _IOC_NRSHIFT = 0 _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS IOC_NONE = 0 IOC_WRITE = 1 IOC_READ = 2 def IOC(dir, type, nr, size): assert dir <= _IOC_DIRMASK, dir assert type <= _IOC_TYPEMASK, type assert nr <= _IOC_NRMASK, nr assert size <= _IOC_SIZEMASK, size return (dir << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT) def IOC_SIZECHECK(t): result = t assert result <= _IOC_SIZEMASK, result return result def IOW(type, nr, size): return IOC(IOC_WRITE, type, nr, IOC_SIZECHECK(size)) def IOR(type, nr, size): return IOC(IOC_READ, type, nr, IOC_SIZECHECK(size))
  • 27. 2. input/output conversion Convert function input/output back and forth. struct.pack() and struct.unpack() are your friends here. def rewind(device): MTREW = 6 mt_com = struct.pack('hi', MTREW, 1) MTIOCTOP = IOW(ord('m'), 1, len(mt_com)) with open(device, 'r') as fd: fcntl.ioctl(fd, MTIOCTOP, mt_com) def status(device): long_size = 8 int_size = 4 status = bytearray(long_size * 5 + int_size * 2) MTIOCGET = IOR(ord('m'), 2, len(status)) with open(device, 'r') as fd: fcntl.ioctl(fd, MTIOCGET, status) status = struct.unpack('lllllii', status) return { "file number": status[-2], "block number": status[-1], "partition": status[1] & 0xff }
  • 28. 3. Iusse ioctl() via fcntl.ioctl(), this is actually the only thing fcntl can do.... def rewind(device): MTREW = 6 mt_com = struct.pack('hi', MTREW, 1) MTIOCTOP = IOW(ord('m'), 1, len(mt_com)) with open(device, 'r') as fd: fcntl.ioctl(fd, MTIOCTOP, mt_com) def status(device): long_size = 8 int_size = 4 status = bytearray(long_size * 5 + int_size * 2) MTIOCGET = IOR(ord('m'), 2, len(status)) with open(device, 'r') as fd: fcntl.ioctl(fd, MTIOCGET, status) status = struct.unpack('lllllii', status) return { "file number": status[-2], "block number": status[-1], "partition": status[1] & 0xff }
  • 29. Comparision Pros Cons cpython extension 最大的控制權 CPython only,要會一 點C ctypes 功能強大、跨平台 複雜,擁有三者中篇幅 最大的文件 fcntl 毫無反應,就只是提供 ioctl() 毫無反應,就只是提供 ioctl()
  • 30. Recap
  • 31. ● Understand your device ● Read driver’s document ● Drive you driver via ioctl() ● Binding it in Python Example code is available on https://github.com/hrchu/playioctl Speaker is available!? on https://medium.com/@petertc