Linux4.19内核使用 NETTLINK bind绑定失败

5 篇文章 0 订阅

在linux4.19的内核使用NETTLINK 时发现总是绑定失败,但是在linux2.6的内核使用时不会出现这种情况。

static void * usb_dev_plug_check(void *arg)
{
    int ret = 0;
    fd_set rset;
    int nread = 0;
    struct timeval select_timeout;
    pthread_set_name("usb_plug_chk");
    
    // 本函数返回值 
    int iResult = 0;
    // 接收内核发来的消息字符串
    char caKernelMsgBuff[1024];
    // 接收内核发来的消息缓冲区大小 
    const unsigned int uiRecvBuffSize = sizeof( caKernelMsgBuff );
    // 套接字地址
    struct sockaddr_nl snl;
    // 套接字文件描述符 
    int sfd = -1;

    // 1.添写套接字地址 
    snl.nl_family = AF_NETLINK;
    snl.nl_pad = 0;
    // 如果希望内核处理消息或多播消息,就把该字段设置为 0,
    // 否则设置为处理消息的进程ID。
//    snl.nl_pid = getpid();
    snl.nl_pid = 0;                        //    这里需要注意!!!!!!!
    snl.nl_groups = 1;

    // 2.创建套接字
    // NETLINK_KOBJECT_UEVENT - 内核消息到用户空间,出现在 Linux 2.6.10
    sfd = socket( PF_NETLINK, // 使用 netlink
                  SOCK_DGRAM, // 使用不连续不可信赖的数据包连接
                  NETLINK_KOBJECT_UEVENT );
    // 如果创建套接字失败
    if (-1 == sfd)
    {
        iResult = -1;
        return NULL;
    }

    // 3.设置套接字接收缓冲区大小
    setsockopt(sfd,
                SOL_SOCKET, // 存取 socket 层
                SO_RCVBUF,    // 设置接收缓冲区大小
                &uiRecvBuffSize,
                sizeof(uiRecvBuffSize));

    // 4.将套接字加入指定的多播组
    iResult = bind(sfd, (struct sockaddr*)&snl, sizeof(snl));
    // 如果将套接字加入指定的多播组失败
    if (-1 == iResult)
    {
        log_error("bind error!");
        goto f_exit;
    }

    while (1)
    {
        //    每次调用select前都要重新设置文件描述符和时间,因为事件发生后,文件描述符和时间都被内核修改了
        select_timeout.tv_sec = 5;
        select_timeout.tv_usec = 0;
        FD_ZERO(&rset);
        FD_SET((unsigned int)sfd, &rset);
        
        ret = select(sfd + 1, &rset, NULL, NULL, &select_timeout);
        if (ret < 0)
        {
            log_error("select fail: %s", strerror(errno));
            continue;
        }
        else if (0 == ret)
        {
            //    超时
            continue;
        }
        else
        {
            nread = recv(sfd, caKernelMsgBuff, sizeof(caKernelMsgBuff), 0);
            if (nread < 0)
            {
                if(EINTR == errno)
                {
                    nread = 0;
                }
                else
                {
                    log_error("recv fail, %s", strerror(errno));
                    continue;
                }
            }
            else if(0 == nread)
            {
                continue;
            }
            else
            {    
                log_info("\n%s\n", caKernelMsgBuff);  
                                
                //    暂时先不区分具体是哪个外设被拔掉,直接退出
                if (NULL != strstr(caKernelMsgBuff, "remove"))
                {
                    //    程序退出
                    log_error("error! usbxxx has been removed!!!");
                    system("sync");
//                    exit(-55);
                }
}

注意程序中的如下两句,使用getpid();就会绑定失败,修改为0后就可以绑定上了。

//    snl.nl_pid = getpid();
    snl.nl_pid = 0;                        //    这里需要注意!!!!!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值