udev&uevent之一 -- udev

本文详细解析了ueventd的启动过程,包括初始化、配置文件解析、设备初始化及事件处理等关键步骤,并展示了ueventd如何监听和响应内核事件。
//@system/core/rootdir/init.rc
on early-init
    start ueventd
....

service ueventd /sbin/ueventd
    critical

//@system/core/init/ueventd.c
int ueventd_main(int argc, char **argv)
+-- get_hardware_name(hardware, &revision);
+-- ueventd_parse_config_file("/ueventd.rc");                   //解析ueventd.rc
+-- snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);     
+-- ueventd_parse_config_file(tmp);                             //解析ueventd.xxx.rc
+-- device_init();
    +-- device_fd = open_uevent_socket();
        +-- struct sockaddr_nl addr;
        +-- memset(&addr, 0, sizeof(addr));
        +-- addr.nl_family = AF_NETLINK;
        +-- addr.nl_pid = getpid();
        +-- addr.nl_groups = 0xffffffff;
        +-- s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);  //创建关联NETLINK_KOBJECT_UEVENT事件的socket
        +-- setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
        +-- setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
        +-- bind(s, (struct sockaddr *) &addr, sizeof(addr)
    +-- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
    +-- fcntl(device_fd, F_SETFL, O_NONBLOCK);
    +-- if (stat(coldboot_done, &info) < 0) {
            t0 = get_usecs();
            coldboot("/sys/class");
            coldboot("/sys/block");
            coldboot("/sys/devices");
            t1 = get_usecs();
            fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000);
            close(fd);
            log_event_print("coldboot %ld uS\n", ((long) (t1 - t0)));
        } else {
            log_event_print("skipping coldboot, already done\n");
        }

+-- ufd.events = POLLIN;
+-- ufd.fd = get_device_fd();
    +-- return device_fd;           //static int device_fd = -1;
+-- while(1) {
        ufd.revents = 0;
        nr = poll(&ufd, 1, -1);     //轮询NETLINK_KOBJECT_UEVENT事件
        if (nr <= 0)
            continue;
        if (ufd.revents == POLLIN)
               handle_device_fd();  //处理轮询到的NETLINK_KOBJECT_UEVENT事件
               /*
               +-- for(;;) {
                       char msg[UEVENT_MSG_LEN+2];
                       struct iovec iov = {msg, sizeof(msg)};
                       struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};
                       ...
                       ssize_t n = recvmsg(device_fd, &hdr, 0); //接收到的msg应该就保存在iov定义的内存段中,即msg[]
                       struct uevent uevent;
                       parse_event(msg, &uevent);               //解析出msg中的uevent事件

                       handle_device_event(&uevent);            //处理添加/删除设备事件
                       handle_firmware_event(&uevent);          //处理加载/卸载firmware事件
                   }
                */
    }








int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 473 char *envp_ext[]) 474 { 475 struct kobj_uevent_env *env; 476 const char *action_string = kobject_actions[action]; 477 const char *devpath = NULL; 478 const char *subsystem; 479 struct kobject *top_kobj; 480 struct kset *kset; 481 const struct kset_uevent_ops *uevent_ops; 482 int i = 0; 483 int retval = 0; 484 485 /* 486 * Mark "remove" event done regardless of result, for some subsystems 487 * do not want to re-trigger "remove" event via automatic cleanup. 488 */ 489 if (action == KOBJ_REMOVE) 490 kobj->state_remove_uevent_sent = 1; 491 492 pr_debug("kobject: '%s' (%p): %s\n", 493 kobject_name(kobj), kobj, __func__); 494 495 /* search the kset we belong to */ 496 top_kobj = kobj; 497 while (!top_kobj->kset && top_kobj->parent) 498 top_kobj = top_kobj->parent; 499 500 if (!top_kobj->kset) { 501 pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " 502 "without kset!\n", kobject_name(kobj), kobj, 503 __func__); 504 return -EINVAL; 505 } 506 507 kset = top_kobj->kset; 508 uevent_ops = kset->uevent_ops; 509 510 /* skip the event, if uevent_suppress is set*/ 511 if (kobj->uevent_suppress) { 512 pr_debug("kobject: '%s' (%p): %s: uevent_suppress " 513 "caused the event to drop!\n", 514 kobject_name(kobj), kobj, __func__); 515 return 0; 516 } 517 /* skip the event, if the filter returns zero. */ 518 if (uevent_ops && uevent_ops->filter) 519 if (!uevent_ops->filter(kobj)) { 520 pr_debug("kobject: '%s' (%p): %s: filter function " 521 "caused the event to drop!\n", 522 kobject_name(kobj), kobj, __func__); 523 return 0; 524 } 525 526 /* originating subsystem */ 527 if (uevent_ops && uevent_ops->name) 528 subsystem = uevent_ops->name(kobj); 529 else 530 subsystem = kobject_name(&kset->kobj); 531 if (!subsystem) { 532 pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the " 533 "event to drop!\n", kobject_name(kobj), kobj, 534 __func__); 535 return 0; 536 } 537 538 /* environment buffer */ 539 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); 540 if (!env) 541 return -ENOMEM; 542 543 /* complete object path */ 544 devpath = kobject_get_path(kobj, GFP_KERNEL); 545 if (!devpath) { 546 retval = -ENOENT; 547 goto exit; 548 } 549 550 /* default keys */ 551 retval = add_uevent_var(env, "ACTION=%s", action_string); 552 if (retval) 553 goto exit; 554 retval = add_uevent_var(env, "DEVPATH=%s", devpath); 555 if (retval) 556 goto exit; 557 retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); 558 if (retval) 559 goto exit; 560 561 /* keys passed in from the caller */ 562 if (envp_ext) { 563 for (i = 0; envp_ext[i]; i++) { 564 retval = add_uevent_var(env, "%s", envp_ext[i]); 565 if (retval) 566 goto exit; 567 } 568 } 569 570 /* let the kset specific function add its stuff */ 571 if (uevent_ops && uevent_ops->uevent) { 572 retval = uevent_ops->uevent(kobj, env); 573 if (retval) { 574 pr_debug("kobject: '%s' (%p): %s: uevent() returned " 575 "%d\n", kobject_name(kobj), kobj, 576 __func__, retval); 577 goto exit; 578 } 579 } 580 581 switch (action) { 582 case KOBJ_ADD: 583 /* 584 * Mark "add" event so we can make sure we deliver "remove" 585 * event to userspace during automatic cleanup. If 586 * the object did send an "add" event, "remove" will 587 * automatically generated by the core, if not already done 588 * by the caller. 589 */ 590 kobj->state_add_uevent_sent = 1; 591 break; 592 593 case KOBJ_UNBIND: 594 zap_modalias_env(env); 595 break; 596 597 default: 598 break; 599 } 600 601 mutex_lock(&uevent_sock_mutex); 602 /* we will send an event, so request a new sequence number */ 603 retval = add_uevent_var(env, "SEQNUM=%llu", ++uevent_seqnum); 604 if (retval) { 605 mutex_unlock(&uevent_sock_mutex); 606 goto exit; 607 } 608 retval = kobject_uevent_net_broadcast(kobj, env, action_string, 609 devpath); 610 mutex_unlock(&uevent_sock_mutex); 611 612 #ifdef CONFIG_UEVENT_HELPER 613 /* call uevent_helper, usually only enabled during early boot */ 614 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { 615 struct subprocess_info *info; 616 617 retval = add_uevent_var(env, "HOME=/"); 618 if (retval) 619 goto exit; 620 retval = add_uevent_var(env, 621 "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 622 if (retval) 623 goto exit; 624 retval = init_uevent_argv(env, subsystem); 625 if (retval) 626 goto exit; 627 628 retval = -ENOMEM; 629 info = call_usermodehelper_setup(env->argv[0], env->argv, 630 env->envp, GFP_KERNEL, 631 NULL, cleanup_uevent_env, env); 632 if (info) { 633 retval = call_usermodehelper_exec(info, UMH_NO_WAIT); 634 env = NULL; /* freed by cleanup_uevent_env */ 635 } 636 } 637 #endif 638 639 exit: 640 kfree(devpath); 641 kfree(env); 642 return retval; 643 }
07-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值