程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了P /调用ioctl系统调用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决P /调用ioctl系统调用?

开发过程中遇到P /调用ioctl系统调用的问题如何解决?下面主要结合日常开发的经验,给出你关于P /调用ioctl系统调用的解决方法建议,希望对你解决P /调用ioctl系统调用有所启发或帮助;

用法示例:

Capability capability;

if (UnsafeNativeMethods.Ioctl(handle, request, ref capability) == -1)
{
    throw new UnixIOException();
}

能力:

[StructLayout(LayoutKind.Sequential, Size = 104)]
internal 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 uint version;

    public CapabilityFlags CapabilitIEs;
}

UnsafeNativeMethods:

internal static class UnsafeNativeMethods
{
    [ReliabilityContract(consistency.WillNotCorruptState, Cer.MayFail)]
    [Dllimport("libc", EntryPoint = "close", SetLastError = truE)]
    internal static extern int Close(IntPtr handlE);

    [Dllimport("libc", EntryPoint = "ioctl", SetLastError = truE)]
    internal static extern int Ioctl(SafeUnixHandle handle, uint request, ref Capability capability);

    [Dllimport("libc", EntryPoint = "open", SetLastError = truE)]
    internal static extern SafeUnixHandle Open(String path, uint flag, int mode);

    internal static String Strerror(int error)
    {
        try
        {
            var buffer = new StringBuilder(256);
            var result = Strerror(error, buffer, (ulong)buffer.Capacity);
            return (result != -1) ? buffer.ToString() : null;
        }
        catch (EntryPointNotFoundException)
        {
            return null;
        }
    }

    [Dllimport("MonoposixHelper", EntryPoint = "Mono_Posix_Syscall_strerror_r", SetLastError = truE)]
    private static extern int Strerror(int error, [Out] StringBuilder buffer, ulong length);
}

SafeUnixHandle:

[SecurityPermission(SecurityAction.inheritanceDemand, UnmanagedCode = truE)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = truE)]
internal sealed class SafeUnixHandle : SafeHandle
{
    [ReliabilityContract(consistency.WillNotCorruptState, Cer.MayFail)]
    private SafeUnixHandle()
        : base(new IntPtr(-1), truE)
    {
    }

    public overrIDe bool IsInvalID
    {
        get { return this.handle == new IntPtr(-1); }
    }

    [ReliabilityContract(consistency.WillNotCorruptState, Cer.MayFail)]
    protected overrIDe bool ReleaseHandle()
    {
        return UnsafeNativeMethods.Close(this.handlE) != -1;
    }
}

UnixIOException:

[serializable]
public class UnixIOException : ExternalException
{
    private Readonly int nativeErrorCode;

    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = truE)]
    public UnixIOException()
        : this(Marshal.GetLastWin32Error())
    {
    }

    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = truE)]
    public UnixIOException(int error)
        : this(error, GetErrormessage(error))
    {
    }

    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = truE)]
    public UnixIOException(String messagE)
        : this(Marshal.GetLastWin32Error(), messagE)
    {
    }

    public UnixIOException(int error, String messagE)
        : base(messagE)
    {
        this.nativeErrorCode = error;
    }

    public UnixIOException(String message, Exception innerException)
        : base(message, innerException)
    {
    }

    protected UnixIOException(serializationInfo info, StreamingContext context)
        : base(info, context)
    {
        this.nativeErrorCode = info.GeTint32("NativeErrorCode");
    }

    public int NativeErrorCode
    {
        get { return this.nativeErrorCode; }
    }

    public overrIDe voID GetobjectData(serializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException("info");
        }

        info.AddValue("NativeErrorCode", this.nativeErrorCodE);
        base.GetobjectData(info, context);
    }

    private static String GetErrormessage(int error)
    {
        var errorDescription = UnsafeNativeMethods.Strerror(error);
        return errorDescription ?? String.Format("UnkNown error (0x{0:x})", error);
    }
}

解决方法

我正在开发一个需要与Video4Linux抽象交互的应用程序。该应用程序使用mono框架以C#开发。

我面临的问题是我无法P /调用ioctl系统调用。或者,更准确地说,我可以P /调用它,但是它崩溃严重。

extern声明如下:

[DllImport("libc",EntryPoint = "ioctl",SetLastError = truE)]
private extern static int KernelIoCtrl(int fd,int request,IntPtr data);

到目前为止,一切都很好。

使用的实际例程KernelIoCtrl如下:

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();
    }
}

以上所有代码似乎都不错。该类IoSpecification用于按照标头规范计算I /
O请求代码(基本上,它遵循处_IOC声明的宏)/usr/include/linux/asm/ioctl.h

data参数是一个结构,声明如下:

[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;
}

应该模仿以下结构(在处声明/usr/include/linux/videodev2.h):

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];
};

在发生崩溃之前,IOCTL请求代码计算存在问题,并且KernelIoCtrl按预期方式工作(返回errno等于 EINVAL
)。当我更正了该错误(并确实具有正确的IOCTRL请求代码)后,该调用已开始导致崩溃。

总而言之,似乎在结构编组中存在问题,但是我看不到它出了什么问题。

我担心问题出在变量参数列表中,因为 ioctl 例程被声明为follow(从man中获取):

int ioctl(int d,...);

但是我看到很多代码将上述例程声明为int ioctl(int d,void*);,并且可以确保特定的IOCTRL请求仅接受一个参数。

大佬总结

以上是大佬教程为你收集整理的P /调用ioctl系统调用全部内容,希望文章能够帮你解决P /调用ioctl系统调用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: