Linux环境下修改为非阻塞read的CAN之代码示例

5 篇文章 2 订阅
3 篇文章 0 订阅

一:何为read阻塞

read( ) 函数 —— 终端输入设备的阻塞与非阻塞的设置

read的相关属性EAGAIN The file descriptor fd refers to a file other than a socket and has been marked non-blocking (O_NONBLOCK), and the write would block.
中文翻译如果文件描述符不是socket的话,该函数是非阻塞的,否则该函数是阻塞的。
说明CAN通信为socket时为阻塞 会使得线程卡住

二:如何设置为非阻塞

// 修改CAN通信的嵌套字为非阻塞
 fcntl(lFdCan,F_SETFL,FNDELAY);//用于设置read函数的非阻塞
lFdCanint嵌套字
F_SETFLCMD参数

三:代码示例

// An highlighted block
main(int argc, char *argv[])
{
    char buff[100];
    pthread_t lPthreadCan1; //用于挂起CAN3的工作线程
    int lFdCan;
    struct ifreq lIfreq;  //接口请求结构体
    struct sockaddr_can lAddrCan; //can总线的地址 同socket编程里面的 socketaddr结构体 用来设置can外设的信息
    struct can_frame lFrameCan;//要发送的buffer
    char can_dev_name0[16];
    char can_dev_name1[16];


    strcpy(can_dev_name0, "can2");
    strcpy(can_dev_name1, "can3");

    if(argc >= 5)
    {
        strncpy(can_dev_name0, argv[3], sizeof(can_dev_name0));
        strncpy(can_dev_name1, argv[4], sizeof(can_dev_name1));
    }

    sprintf(buff, "ip link set can2 down ");
    system(buff);  //将can2关闭
    sprintf(buff, "ip link set can3 down ");
    system(buff);  //将can3关闭


    sprintf(buff, "ip link set %s up type can bitrate 800000", can_dev_name0);
    system(buff);  //将can2以800k的速率挂起
    sprintf(buff, "ip link set %s up type can bitrate 800000", can_dev_name1);
    system(buff);  //将can3以800k的速率挂起

    pthread_create(&lPthreadCan1, NULL, thread_can1_recive, can_dev_name1);//创建CAN3线程,参数can_dev_name1以CAN3导入
    lFdCan = socket(PF_CAN, SOCK_RAW, CAN_RAW);//创建套接字
    if(lFdCan < 0)
    {
        printf("%s fail: create socket\n", can_dev_name0);
        return -1;
    }
    strcpy(lIfreq.ifr_name, can_dev_name0);
    if(ioctl(lFdCan, SIOCGIFINDEX, &lIfreq)) //指定 can2 设备
    {
        printf("%s fail: ioctl SIOCGIFINDEX\n", can_dev_name0);
        goto ERROR0;
    }

    lAddrCan.can_family = AF_CAN;//协议类型
    lAddrCan.can_ifindex = lIfreq.ifr_ifindex;//can总线外设的具体索引 类似 ip地址
    if(bind(lFdCan, (struct sockaddr*)&lAddrCan, sizeof(lAddrCan)))//将套接字和canbus外设进行绑定,即套接字与 can0 绑定
    {
        goto ERROR0;
    }
	
	 fcntl(lFdCan,F_SETFL,FNDELAY);//用于设置read函数的非阻塞
	
	
    if(setsockopt(lFdCan, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0))//禁用过滤规则,本进程不接收报文,只负责发送
    {
        printf("%s fail: setsockopt CAN_RAW_FILTER\n", can_dev_name0);
    }


    while(recive_done == 0)
    {
        lFrameCan.can_id  = 0x11;//设置地址
        lFrameCan.can_dlc = sprintf((char *)lFrameCan.data, "%s", "alinx");//将alinx写入发送区并赋予can_dlc其长度
        write(lFdCan, &lFrameCan, sizeof(lFrameCan));//发送
        sleep(1);
        lFrameCan.can_id  = 0x12;
        lFrameCan.can_dlc = sprintf((char *)lFrameCan.data, "%s", "alinxa");
        write(lFdCan, &lFrameCan, sizeof(lFrameCan));
        sleep(1);
    }
    if(argc >= 3)
    {
        sprintf(buff, "echo ok >> %s/%s", argv[1], argv[2]);
        system(buff);
    }
    return 0;
ERROR0:
    close(lFdCan);
    return -2;
}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常抱歉,我之前给出的示例代码是基于 Windows 平台的。以下是在 Linux 环境下使用 QT QPrinter 类和 emf 库(GetEnhMetaFile方式) 对 emf 文件进行展示的示例代码: ```cpp #include <QtWidgets> #include <QtPrintSupport> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle("EMF Viewer"); QVBoxLayout *layout = new QVBoxLayout(&window); QScrollArea *scrollArea = new QScrollArea(&window); layout->addWidget(scrollArea); QLabel *label = new QLabel(scrollArea); scrollArea->setWidget(label); QString fileName = QFileDialog::getOpenFileName(&window, "Open EMF File", QString(), "EMF Files (*.emf)"); if (!fileName.isEmpty()) { QPrinter printer(QPrinter::HighResolution); printer.setPageSize(QPrinter::A4); printer.setOutputFormat(QPrinter::NativeFormat); printer.setOutputFileName(fileName); QPainter painter(&printer); if (painter.begin(&printer)) { int fh = open(fileName.toLocal8Bit().constData(), O_RDONLY); Q_ASSERT(fh != -1); struct stat st; Q_ASSERT(fstat(fh, &st) != -1); char *data = static_cast<char *>(mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fh, 0)); HENHMETAFILE hemf = SetEnhMetaFileBits(st.st_size, data); munmap(data, st.st_size); close(fh); painter.drawEnhancedMetaFile(hemf, QRect()); DeleteEnhMetaFile(hemf); painter.end(); } QPixmap pixmap(fileName); label->setPixmap(pixmap); } window.show(); return app.exec(); } ``` 需要包含的头文件有: - `<QtWidgets>`:Qt Widgets 模块的头文件,用于使用 `QApplication`、`QWidget`、`QVBoxLayout`、`QScrollArea`、`QLabel` 和 `QFileDialog` 等类。 - `<QtPrintSupport>`:Qt 打印支持模块的头文件,用于使用 `QPrinter` 和 `QPainter` 等类。 - `<sys/types.h>`:Linux 系统类型的头文件,用于使用 `open` 和 `fstat` 等函数。 - `<sys/stat.h>`:Linux 文件状态的头文件,用于使用 `fstat` 函数。 - `<fcntl.h>`:文件控制的头文件,用于使用 `open` 函数。 - `<sys/mman.h>`:内存映射的头文件,用于使用 `mmap` 和 `munmap` 函数。 在 Linux 环境下,需要使用 `SetEnhMetaFileBits` 函数将 EMF 文件转换为句柄,然后使用 `DeleteEnhMetaFile` 函数删除句柄。需要注意的是,使用 `mmap` 函数将 EMF 文件映射到进程的地址空间中,然后使用 `SetEnhMetaFileBits` 函数将映射的数据转换为句柄。 希望这次提供的信息对您有所帮助。如果您还有任何疑问,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值