将()写入sysfs条目/sys/bus/pci/devices/../driver/remove\u id失败

将()写入sysfs条目/sys/bus/pci/devices/../driver/remove\u id失败,c,linux,pci,sysfs,C,Linux,Pci,Sysfs,在/sys/bus/pci/devices/../driver/remove_id file上看到write()函数失败,返回-1,且errno等于19(ENODEV) 但是,通过命令行也可以很好地工作。我已经检查了文件权限,用户对该文件执行写操作的权限(--w-------)似乎没有问题 int fp = 0; int buffer_length = 0; int bytes_written = 0; fp = open(cmd_buf, O_WRONLY); // where cmd_bu

在/sys/bus/pci/devices/../driver/remove_id file上看到write()函数失败,返回-1,且errno等于19(ENODEV

但是,通过命令行也可以很好地工作。我已经检查了文件权限,用户对该文件执行写操作的权限(--w-------)似乎没有问题

int fp = 0;
int buffer_length = 0;
int bytes_written = 0;

fp = open(cmd_buf, O_WRONLY); // where cmd_buf will hold this string 
                              // "/sys/bus/pci/devices/.../driver/remove_id"
if (fp == -1)
{
    return -1;
}

// where inbuf will be a char * pointing to pci vendor device id like 
// this, "XXXX YYYY"
bytes_written = write(fp, in_buf, sizeof(in_buf));
printf(" bytes_written : %d \n ", bytes_written);
看到写入的字节数等于-1并且errno显示19

如果您发现代码片段有问题,请告诉我?

两个可能的问题:

  • 在write()系统调用中使用sizeof(in_buf)写入字符串“vendorId deviceId”,如果in_buf[]大于10个字符,则后面可能有更多的垃圾数据
  • 也许in_buf不是一个表,而是一个指针,因此,sizeof(in_buf)将返回4或8(32位或64位系统的指针大小),而不是它所指向的字符串的长度
  • 因此,在这两种情况下(定义为表或指针),strlen(in_buf)而不是sizeof(in_buf)是最安全的数据写入长度解决方案,前提是字符串以“\0”结尾。

    两个可能的问题:

  • 在write()系统调用中使用sizeof(in_buf)写入字符串“vendorId deviceId”,如果in_buf[]大于10个字符,则后面可能有更多的垃圾数据
  • 也许in_buf不是一个表,而是一个指针,因此,sizeof(in_buf)将返回4或8(32位或64位系统的指针大小),而不是它所指向的字符串的长度

  • 因此,在这两种情况下(定义为表或指针),strlen(in_buf)而不是sizeof(in_buf)是最安全的数据写入长度解决方案,前提是字符串以“\0”结尾。

    您没有提供足够的信息来确定问题所在

    但是,下面是一个示例程序example.c,它表明是您的实现存在错误:

    #定义POSIX_C_SOURCE200809L
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    /*将字符串“数据”写入“路径”处的现有文件或设备。
    如果成功,则返回0,否则返回错误代码。
    */
    int write_文件(常量字符*路径,常量字符*数据)
    {
    常量字符*常量结束=(数据)?数据+字符串(数据):数据;
    (三);
    int-fd;
    /*NULL或空路径无效*/
    如果(!path | |!*path)
    返回errno=EINVAL;
    fd=开放(路径,O|u WRONLY | O|u CREAT | O|u TRUNC | O|u nocty | O|u CLOEXEC,0666);
    如果(fd==-1)
    返回errno;/*errno已由open()设置*/
    /*写下数据的内容*/
    while(数据<结束){
    n=写入(fd,数据,(大小_t)(结束-数据));
    如果(n>0){
    /*写入n个字节*/
    数据+=n;
    }否则
    如果(n!=-1){
    /*C库错误:永远不会发生*/
    关闭(fd);
    返回errno=EIO;
    }否则{
    /*errno中的错误*/
    const int saved_errno=errno;
    关闭(fd);
    返回errno=saved\u errno;
    }
    }
    如果(关闭(fd)=-1){
    /*close()可以报告延迟的I/O错误*/
    返回errno;
    }
    /*成功*/
    返回0;
    }
    静态无效用法(常量字符*argv0)
    {
    fprintf(标准格式,“\n”);
    fprintf(stderr,“用法:%s[-h |--help]\n”,argv0);
    fprintf(stderr,“%s文件内容\n”,argv0);
    fprintf(标准格式,“\n”);
    fprintf(stderr,“这与'echo-n\'CONTENTS\>FILE.\n'的作用相同);
    fprintf(标准格式,“\n”);
    }
    int main(int argc,char*argv[])
    {
    如果(argc<2){
    用法((argv&&argv[0]&&argv[0][0])?argv[0]:“(this)”;
    返回退出成功;
    }否则
    如果(argc>3){
    用法((argv&&argv[0]&&argv[0][0])?argv[0]:“(this)”;
    返回退出失败;
    }否则
    如果(!strcmp(argv[1],“-h”)| |!strcmp(argv[1],“-help”)){
    用法((argv&&argv[0]&&argv[0][0])?argv[0]:“(this)”;
    返回退出成功;
    }
    if(写入_文件(argv[1],argv[2])){
    fprintf(标准字符,“%s:%s.\n”,argv[1],strerror(errno));
    返回退出失败;
    }
    返回退出成功;
    }
    
    使用例如
    gcc-Wall-Wextra-O2 example.c-o example
    编译它,并使用例如
    /example/sys/bus/pci/devices/../driver/remove_id“vendor_id device_id”运行它
    。 在没有参数的情况下运行它,或者将
    -h
    --help
    作为唯一的参数运行,它会将使用信息打印到标准错误

    该程序基本上实现了echo-n“vendor\u id device\u id”>/sys/bus/pci/devices/../drivers/remove\u id的功能

    如果成功,它将不输出任何内容,只返回success(退出状态0)。如果存在任何类型的错误,它将向标准错误报告

    如果您知道目标路径始终是设备或伪文件(如/sys或/proc中的路径),请使用
    fd=open(path,O_WRONLY | O_nocty | O_CLOEXEC)取而代之
    O_CLOEXEC
    意味着,如果进程在任何点分叉,则不会将此特定文件描述符复制到子进程
    O_NOCTTY
    意味着如果路径是一个tty设备,并且当前进程没有控制终端,那么内核不会将打开的设备作为控制终端

    echo-n
    使用
    O|u CREAT | O|u TRUNC
    ,这样,如果目标路径存在并且是一个普通文件,它将被截断,但是如果它不存在,它将被创建。它不影响打开现有的字符设备和伪文件。无论何时使用
    O_create
    ,都必须有第三个参数,它会影响所创建文件的访问模式。此模式通常为
    0666
    ,允许由当前umask调节的读写访问。可以使用
    mode\u t mask=umask(0)获得当前umask;乌马斯克(马萨诸塞州)