当前位置: 首页 > 工具软件 > dhcpcd > 使用案例 >

dhcpcd守护进程分析【转】

洪英豪
2023-12-01

本文转载自;http://blog.csdn.net/lishanmin11/article/details/37930073

最近在调android ethernet功能,android本身不带 ethernet 功能,需要打patch。这个patch可以在setting里出来 ethernet configuration 选项。即添加了用户配置IP的功能。
我打上patch之后,点击选上DHCP功能,结果路由器一直不能自动分配IP。

经检测,命令行里运行 netcfg eth0 up dhcp 时,ethernet能被正常启动,DHCP能分配到IP。

但是Setting里选上时,dhcp却不能正常分配IP。 这很费解,我先后查看了,
/system/core/libnetutils/*
/externel/dhcpcd/* 
发现都没什么问题。

在Setting中点击turn on ethernet选项时,从log看到能调到

  1. E/EthernetStateTracker( 185): DhcpHandler: DHCP request failed: Timed out waiting for dhcpcd to start
  2. D/EthernetStateTracker( 185): DhcpHandler: DHCP request started


说明patch是好的能正常工作,能正常掉用dhcp,只是DHCP运行不成功。

然后我查了 getprop: 显示 init.svc.dhcpcd_eth0 = stop
正常应该是running的,这样DHCP 才能运行成功。

最后调试了两天,才搞明白,原来是 init.rc 中 dhcpcd_eth0 守护进程的问题:

改成:

  1. on property:init.svc.dhcpcd_eth0=stopped
  2.     start dhcpcd_eth0
  3. service dhcpcd_eth0 /system/bin/dhcpcd -ABKL -f /system/etc/dhcpcd/dhcpcd.conf -d eth0
  4.     class main
  5.     disabled
  6.     oneshot


这样就可以了。

这时init.svc.dhcpcd_eth0 就会是 running 了。这时再点击Setting -> ethernet configuration, DHCP就能正常分配IP了。

libnetutils 和dhcpcd 调用过程如下:

1. libnetutils 调用过程:

  1. jni
  2. =>runDhcp
  3. =>android_net_utils_runDhcp
  4. libs/netutils/dhcp_utils.c
  5. =>dhcp_do_request
  6. =>
  7. static const char DAEMON_NAME[] = "dhcpcd";
  8. static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd";
  9. static const char DHCP_PROP_NAME_PREFIX[] = "dhcp";
  10. const char *ctrl_prop = "ctl.start";
  11. const char *desired_status = "running";
  12. snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
  13. DHCP_PROP_NAME_PREFIX,
  14. interface);
  15. property_set(result_prop_name, "");//设置dhcp.eth0.result="";等到成功完成dhcp之后,
  16. property_set(ctrl_prop, DAEMON_NAME);//向名字为dhcpcd的service,发送"ctrl.start"启动命令字,该service在init.rc中
  17. //init.rc中dhcpcd服务进程命令字
  18. //service dhcpcd /system/bin/dhcpcd eth0
  19. // disabled
  20. // oneshot
  21. wait_for_property(DAEMON_PROP_NAME, desired_status, 10);
  22. //init.c=>init进程
  23. //=>handle_property_set_fd因为是"ctrl.start"命令字,所以调用handle_control_message处理控制信息
  24. //=>handle_control_message
  25. //=>msg_start
  26. //=>
  27. // struct service *svc = service_find_by_name(name);
  28. // service_start(svc);//启动svc,即执行:/system/bin/dhcpcd eth0
  29. //=>service_start
  30. //=>pid = fork();
  31. // if(pid == 0)execve(svc->args[0], (char**) svc->args, (char**) ENV);子进程执行execve运行/system/bin/dhcpcd,参数为eth0
  32. //=>否则父进程,即init进程将
  33. //=>notify_service_state(svc->name, "running");设置该svc的状态prop
  34. // snprintf(pname, sizeof(pname), "init.svc.%s", name);
  35. // property_set(pname, state);//所以这样上面wait_for_property(DAEMON_PROP_NAME, desired_status, 10);也才能够正常pass[luther.gliethttp].
  36. wait_for_property(result_prop_name, NULL, 15);//等待dhcp.eth0.result=非空


2. dhcpcd 调用过程:


    1. system/extra/dhcpcd-4.0.0-beta9/dhcpcd.c
    2. dhcpcd
    3. =>main
    4. # define SYSCONFDIR "/system/etc/dhcpcd"
    5. #define PACKAGE "dhcpcd"
    6. # define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
    7. # define LIBEXECDIR "/system/etc/dhcpcd"
    8. # define SCRIPT LIBEXECDIR "/" PACKAGE "-run-hooks"
    9. =>strlcpy(options->script, SCRIPT, sizeof(options->script));//默认的options->script="/system/etc/dhcpcd /dhcpcd-run-hooks"
    10. =>f = fopen(cf ? cf : CONFIG, "r");//如果没有指定.conf文件,那么使用默认.conf文件
    11. =>parse_config_line//解析"/system/etc/dhcpcd/dhcpcd.conf"默认配置文件
    12. =>parse_option
    13. =>如果在"/system/etc/dhcpcd/dhcpcd.conf"有"script"这个节
    14. =>那么执行strlcpy(options->script, oarg, sizeof(options->script));直接拷贝
    15. /*
    16. {"script", required_argument, NULL, 'c'},
    17. {"option", required_argument, NULL, 'o'},
    18. "/system/etc/dhcpcd/dhcpcd.conf"中的部分内容如下:
    19. ...
    20. option domain_name_servers, domain_name, domain_search, host_name
    21. ...
    22. */
    23. =>dhcp_run
    24. =>handle_dhcp_packet
    25. =>handle_dhcp
    26. =>bind_dhcp
    27.   reason = "TIMEOUT";reason = "BOUND";reason = "REBIND";reason = "RENEW";
    28. system/extra/dhcpcd-4.0.0-beta9/configure.c
    29. => configure(iface, reason, state->new, state->old, &state->lease, options, 1);
    30. //如果dhcp超时或者dhcp成功,都会调用exec_script来执行脚本,
    31. //执行setprop dhcp.${interface}.result "failed"或者
    32. //执行setprop dhcp.${interface}.result "ok"
    33. =>exec_script(options, iface->name, reason, NULL, old);
    34. =>然后configure_env通过环境变量将reason传递到脚本中
    35. int exec_script(const struct options *options, const char *iface, const char *reason,
    36.      const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
    37. =>pid = fork();
    38. =>if(pid == 0)execve(options->script, argv, env);//子进程执行脚本,默认"/system/etc/dhcpcd/dhcpcd-run-hooks"
    39. //dhcpcd-run-hooks脚本会根据level值,决定是否执行system/etc/dhcpcd/dhcpcd-hook/*目录下的相应文件
    40. //我们的系统在该system/etc/dhcpcd/dhcpcd-hook/*目录下有如下3个文件
    41. //95-configured
    42. //20-dns.conf
    43. //01-test
    44. =>父进程返回while (waitpid(pid, &status, 0) == -1)等待子进程脚本执行完成
    45. system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/20-dns.conf
    46. system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/95-configured
    47.     ...
    48.     setprop dhcp.${interface}.ipaddress "${new_ip_address}"
    49.     setprop dhcp.${interface}.result "ok"//设置属性为ok
    50.     setprop dhcp.${interface}.result "failed"
    51.     ...

转载于:https://www.cnblogs.com/zzb-Dream-90Time/p/8243982.html

 类似资料: