c - 无法将完整脚本写入串行端口上的设备

标签 c linux

脚本文件有6000多个字节被复制到缓冲区中。缓冲区的内容然后写入连接到串行端口的设备。但是写入函数只返回4608字节,而缓冲区包含6117字节。I我无法理解为什么会这样。

{   
    FILE *ptr;

    long numbytes;
    int i;
    ptr=fopen("compass_script(1).4th","r");//Opening the script file

    if(ptr==NULL)
        return 1;

    fseek(ptr,0,SEEK_END);

    numbytes = ftell(ptr);//Number of bytes in the script 
    printf("number of bytes in the calibration script %ld\n",numbytes);
    //Number of bytes in the script is 6117.                      
    fseek(ptr,0,SEEK_SET);
    char writebuffer[numbytes];//Creating a buffer to copy the file

    if(writebuffer == NULL)
        return 1;

    int s=fread(writebuffer,sizeof(char),numbytes,ptr);
    //Transferring  contents into the buffer

    perror("fread");

    fclose(ptr);

    fd = open("/dev/ttyUSB3",O_RDWR | O_NOCTTY | O_NONBLOCK);
    //Opening serial port

    speed_t baud=B115200;

    struct termios serialset;//Setting a baud rate for communication

    tcgetattr(fd,&serialset);

    cfsetispeed(&serialset,baud);
    cfsetospeed(&serialset,baud);

    tcsetattr(fd,TCSANOW,&serialset); 

    long bytesw=0;
    tcflush(fd,TCIFLUSH);
    printf("\nnumbytes %ld",numbytes);
    bytesw=write(fd,writebuffer,numbytes);
    //Writing the script into the  device connected to the serial port

    printf("bytes written%ld\n",bytesw);//Only 4608 bytes are written

    close (fd);
    return 0;
}

最佳答案

嗯,这就是规范。当您写入文件时,您的进程通常会被阻塞,直到整个数据被写入。这意味着只有当所有数据都写入磁盘缓冲区后,您的进程才会再次运行。对于设备来说情况并非如此,因为设备驱动程序负责确定一次写入要写入多少数据。这意味着,根据设备驱动程序的不同,您将获得所有数据驱动,仅部分数据驱动,甚至根本没有数据驱动。这仅取决于设备以及驱动程序如何实现其控制。

在地板上,设备驱动程序通常只有有限的内存来填充缓冲区,并且能够接受有限数量的数据。这里有两个策略,驱动程序可以阻止进程,直到有更多的缓冲区空间可用于处理它,或者它可以返回部分只写。

您的程序有责任接受部分读取并继续写入缓冲区的其余部分,或者将问题传递回客户端模块并再次仅返回部分写入。这种方法是最灵活的一种,并且是到处实现的一种。现在您有了部分写入的理由,但球在您的屋顶上,您必须决定下一步该做什么。

此外,当您使用 long 作为 ftell() 函数调用返回值和 int 作为 fwrite () 函数调用... 虽然你的数据量不大,也不太可能这个值不能分别转换成longint,但是两个调用的返回类型分别是 size_tssize_t。 (就像用于波特率值的 speed_t 类型)long 可以是 32 位,size_t 是 64 位类型。

你能做的最好的事情就是确保整个缓冲区是由一些代码片段编写的,如下一个:

char *p = buffer;
while (numbytes > 0) {
    ssize_t n = write(fd, p, numbytes);
    if (n < 0) {
        perror("write");
        /* driver signals some error */
        return 1;
    }
    /* writing 0 bytes is weird, but possible, consider putting
     * some code here to cope for that possibility. */
    /* n >= 0 */
    /* update pointer and numbytes */
    p += n;
    numbytes -= n;
}
/* if we get here, we have written all numbytes */

关于c - 无法将完整脚本写入串行端口上的设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45325320/

相关文章:

c - 发送 SKB 以从内核空间传输

c - 如何让守护进程与C中的子进程通信

linux - df-h 和 fdisk 命令的区别

用于更改文件中文本的 Linux 实用程序

c# - 可以在 Linux 中使用 MonoDevelop 编译 Visual Studio 2010 .Net 项目吗?

linux - 如何显示文件中bash shell的所有命令? Linux

c++ - 在链接规范(extern "C",extern "C++")中,在 C++ 代码中包含标准 C header 的指定行为是什么?

统计最大数出现的次数

c - 如何扫描时间?

linux - FastCGI with perl - 在共享 Linux 虚拟主机上