P / Aufruf eines ioctl-Systemaufrufs
Ich entwickle eine Anwendung, die mit der Video4Linux-Abstraktion interagieren muss. Die Anwendung wird in C # unter Verwendung des Mono-Frameworks entwickelt.
Das Problem, mit dem ich konfrontiert bin, ist, dass ich das nicht P / Invoke kannioctl
Systemaufruf. Genauer gesagt, ich kann es P / Invoke, aber es stürzt ab.
Die externe Erklärung lautet wie folgt:
<code>[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)] private extern static int KernelIoCtrl(int fd, int request, IntPtr data); </code>
So weit, ist es gut.
Die tatsächliche Routine, die das verwendetKernelIoCtrl
ist das Folgende:
<code>protected virtual int Control(IoSpecification request, object data) { GCHandle dataHandle; IntPtr dataPointer = IntPtr.Zero; try { // Pin I/O control data if (data != null) { dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); dataPointer = dataHandle.AddrOfPinnedObject(); } // Perform I/O control int result = KernelIoCtrl(mFileDescriptor, request.RequestCode, dataPointer); int errno = Marshal.GetLastWin32Error(); // Throw exception on errors if (errno != (int)ErrNumber.NoError) throw new System.ComponentModel.Win32Exception(errno); return (result); } finally { if (dataPointer != IntPtr.Zero) dataHandle.Free(); } } </code>
Der gesamte obige Code scheint gut zu sein. Die KlasseIoSpecification
wird für die Berechnung des E / A-Anforderungscodes nach der Header-Spezifikation verwendet (im Grunde folgt er der_IOC
Makro deklariert um/usr/include/linux/asm/ioctl.h
.
Dasdata
Parameter ist eine wie folgt deklarierte Struktur:
<code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Capability { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string Driver; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string Device; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string BusInfo; public UInt32 Version; public CapabilityFlags Capabilities; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public UInt32[] Reserved; } </code>
welche die folgende Struktur imitieren sollte (deklariert bei/usr/include/linux/videodev2.h
):
<code>struct v4l2_capability { __u8 driver[16]; /* i.e. "bttv" */ __u8 card[32]; /* i.e. "Hauppauge WinTV" */ __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ __u32 version; /* should use KERNEL_VERSION() */ __u32 capabilities; /* Device capabilities */ __u32 reserved[4]; }; </code>
Vor dem Absturz gab es ein Problem bei der Berechnung des IOCTL - AnforderungscodesKernelIoCtrl
hat wie erwartet funktioniert (Rückgabe eineserrno
ist gleichEINVAL). Als ich den Fehler behoben habe (und tatsächlich den richtigen IOCTRL-Anforderungscode habe), hat der Aufruf begonnen, einen Absturz zu verursachen.
Zusammenfassend scheint es ein Problem beim Struktur-Marshalling zu geben, aber ich kann nicht erkennen, was falsch läuft.
Ich befürchte, dass das Problem die Liste der variablen Argumente ist, weil dieioctl Routine wird wie folgt deklariert (vom Menschen genommen):
<code>int ioctl(int d, int request, ...); </code>
Aber ich sah viel Code, der die obige Routine als deklarierteint ioctl(int d, int request, void*);
und ich kann sicherstellen, dass die spezifische IOCTRL-Anforderung nur ein Argument akzeptiert.