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.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage