dhcpcd守护进程分析

最近在调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.     ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值