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

时间:2017-07-26 11:14:21

标签: c linux

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

另外,请注意,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 */