在中文版的 Mac OS裡,系統會自動依照安裝時給的中文姓名翻譯成英文作為主機名稱。對我來說因為常常會用shell底下操作,就超想改hostname,方法如下:
直接編輯"系統偏好設定"/"共享"/"電腦名稱"即可,後面的".local"不用理他。
打開終端機之後就可以看到hostname修改好了。
-
參考資料:
- 更改 Mac 主機名稱
static const struct net_device_ops nic_netdev_ops = { /* Kernel calls ndo_open() and ndo_validate_addr() * when you bring up the NIC */ .ndo_open = nic_open, .ndo_validate_addr = nic_validate_addr, /* when you shut down the NIC, kernel call the .ndo_stop() */ .ndo_stop = nic_close, /* Kernel calls ndo_start_xmit() when it wants to * transmit a packet. */ .ndo_start_xmit = nic_start_xmit, /* ndo_change_mtu() is called, when you change MTU */ .ndo_change_mtu = nic_change_mtu, /* ndo_set_mac_address() is called, * when you change the MAC addr */ .ndo_set_mac_address = nic_set_mac_addr, };
static int nic_validate_addr(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_validate_addr(netdev); } static int nic_change_mtu(struct net_device *netdev, int new_mtu) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_change_mtu(netdev, new_mtu); } static int nic_set_mac_addr(struct net_device *netdev, void *addr) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_mac_addr(netdev, addr); }
/* reference ldd3, snull.c */ #include <linux/module.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> /* for in_device, in_ifaddr */ #include <linux/inetdevice.h> MODULE_AUTHOR("Brook"); MODULE_DESCRIPTION("Kernel module for demo"); MODULE_LICENSE("GPL"); #define MAX_ETH_FRAME_SIZE 1792 struct nic_priv { /* you can use array to queue more packet */ unsigned char *tx_buf; unsigned int tx_len; u32 msg_enable; }; static struct net_device *nic_dev[2]; /* netif msg type, defined in netdevice.h NETIF_MSG_DRV = 0x0001, NETIF_MSG_PROBE = 0x0002, NETIF_MSG_LINK = 0x0004, NETIF_MSG_TIMER = 0x0008, NETIF_MSG_IFDOWN = 0x0010, NETIF_MSG_IFUP = 0x0020, NETIF_MSG_RX_ERR = 0x0040, NETIF_MSG_TX_ERR = 0x0080, NETIF_MSG_TX_QUEUED = 0x0100, NETIF_MSG_INTR = 0x0200, NETIF_MSG_TX_DONE = 0x0400, NETIF_MSG_RX_STATUS = 0x0800, NETIF_MSG_PKTDATA = 0x1000, NETIF_MSG_HW = 0x2000, NETIF_MSG_WOL = 0x4000, */ #define DEF_MSG_ENABLE 0xffff static void dump(unsigned char *buf) { unsigned char *p, sbuf[2*(sizeof(struct ethhdr) + sizeof(struct iphdr))]; int i; p = sbuf; for(i = 0; i < sizeof(struct ethhdr); i++) { p += sprintf(p, "%02X ", buf[i]); } printk("eth %s\n", sbuf); p = sbuf; for(i = 0; i < sizeof(struct iphdr); i++) { p += sprintf(p, "%02X ", buf[sizeof(struct ethhdr) + i]); } printk("iph %s\n", sbuf); p = sbuf; for(i = 0; i < 4; i++) { p += sprintf(p, "%02X ", buf[sizeof(struct ethhdr) + sizeof(struct iphdr) + i]); } printk("payload %s\n", sbuf); } static void nic_rx(struct net_device *netdev, int len, unsigned char *buf) { struct sk_buff *skb; struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, hw, netdev, "%s(#%d), rx:%d\n", __func__, __LINE__, len); /* * The packet has been retrieved from the transmission * medium. Build an skb around it, so upper layers can handle it */ skb = dev_alloc_skb(len + 2); if (!skb) { netif_err(priv, rx_err, netdev, "%s(#%d), rx: low on mem - packet dropped\n", __func__, __LINE__); netdev->stats.rx_dropped++; return; } skb_reserve(skb, 2); /* align IP on 16B boundary */ memcpy(skb_put(skb, len), buf, len); /* Write metadata, and then pass to the receive level */ skb->dev = netdev; skb->protocol = eth_type_trans(skb, netdev); skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ netdev->stats.rx_packets++; netdev->stats.rx_bytes += len; netif_rx(skb); } static int nic_open(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, ifup, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); /* may be using DMA */ priv->tx_buf = kmalloc(MAX_ETH_FRAME_SIZE, GFP_KERNEL); if (priv->tx_buf == NULL) { netif_info(priv, ifup, netdev, "%s(#%d), cannot alloc tx buf\n", __func__, __LINE__); return -ENOMEM; } netif_start_queue(netdev); return 0; } static int nic_close(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, ifdown, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); netif_stop_queue(netdev); return 0; } static void nic_hw_xmit(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); struct iphdr *iph; u32 *saddr, *daddr; struct in_device* in_dev; struct in_ifaddr* if_info; if (priv->tx_len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { netif_info(priv, hw, netdev, "%s(#%d), too short\n", __func__, __LINE__); return; } dump(priv->tx_buf); iph = (struct iphdr *)(priv->tx_buf + sizeof(struct ethhdr)); saddr = &iph->saddr; daddr = &iph->daddr; netif_info(priv, hw, netdev, "%s(#%d), orig, src:%pI4, dst:%pI4, len:%d\n", __func__, __LINE__, saddr, daddr, priv->tx_len); in_dev = nic_dev[(netdev == nic_dev[0] ? 1 : 0)]->ip_ptr; if (in_dev) { if_info = in_dev->ifa_list; for (if_info = in_dev->ifa_list; if_info; if_info=if_info->ifa_next) { #if 0 printk("label:%s, address=%pI4\n", if_info->ifa_label, &if_info->ifa_address); #endif *saddr = *daddr = if_info->ifa_address; ((u8 *)saddr)[3]++; netif_info(priv, hw, netdev, "%s(#%d), new, src:%pI4, dst:%pI4\n", __func__, __LINE__, saddr, daddr); break; } if (!if_info) { /* drop packet */ netdev->stats.tx_dropped++; netif_info(priv, hw, netdev, "%s(#%d), drop packet\n", __func__, __LINE__); return; } } iph->check = 0; /* and rebuild the checksum (ip needs it) */ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); netdev->stats.tx_packets++; netdev->stats.tx_bytes += priv->tx_len; nic_rx(nic_dev[(netdev == nic_dev[0] ? 1 : 0)], priv->tx_len, priv->tx_buf); } static netdev_tx_t nic_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), orig, src:%pI4, dst:%pI4\n", __func__, __LINE__, &(ip_hdr(skb)->saddr), &(ip_hdr(skb)->daddr)); priv->tx_len = skb->len; if (likely(priv->tx_len < MAX_ETH_FRAME_SIZE)) { if (priv->tx_len < ETH_ZLEN) { memset(priv->tx_buf, 0, ETH_ZLEN); priv->tx_len = ETH_ZLEN; } skb_copy_and_csum_dev(skb, priv->tx_buf); dev_kfree_skb_any(skb); } else { dev_kfree_skb_any(skb); netdev->stats.tx_dropped++; return NETDEV_TX_OK; } nic_hw_xmit(netdev); return NETDEV_TX_OK; } static int nic_validate_addr(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_validate_addr(netdev); } static int nic_change_mtu(struct net_device *netdev, int new_mtu) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_change_mtu(netdev, new_mtu); } static int nic_set_mac_addr(struct net_device *netdev, void *addr) { struct nic_priv *priv = netdev_priv(netdev); netif_info(priv, drv, netdev, "%s(#%d), priv:%p\n", __func__, __LINE__, priv); return eth_mac_addr(netdev, addr); } /* * This function is called to fill up an eth header, since arp is not * available on the interface */ int snull_header(struct sk_buff *skb, struct net_device *netdev, unsigned short type, const void *daddr, const void *saddr, unsigned len) { struct nic_priv *priv = netdev_priv(netdev); struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); struct net_device *dst_netdev; netif_info(priv, drv, netdev, "%s(#%d)\n", __func__, __LINE__); dst_netdev = nic_dev[(netdev == nic_dev[0] ? 1 : 0)]; eth->h_proto = htons(type); memcpy(eth->h_source, saddr ? saddr : netdev->dev_addr, netdev->addr_len); memcpy(eth->h_dest, dst_netdev->dev_addr, dst_netdev->addr_len); return (netdev->hard_header_len); } static const struct header_ops snull_header_ops = { .create = snull_header, }; static const struct net_device_ops nic_netdev_ops = { /* Kernel calls ndo_open() and ndo_validate_addr() * when you bring up the NIC */ .ndo_open = nic_open, .ndo_validate_addr = nic_validate_addr, /* when you shut down the NIC, kernel call the .ndo_stop() */ .ndo_stop = nic_close, /* Kernel calls ndo_start_xmit() when it wants to * transmit a packet. */ .ndo_start_xmit = nic_start_xmit, /* ndo_change_mtu() is called, when you change MTU */ .ndo_change_mtu = nic_change_mtu, /* ndo_set_mac_address() is called, * when you change the MAC addr */ .ndo_set_mac_address = nic_set_mac_addr, }; static struct net_device* nic_alloc_netdev(void) { struct net_device *netdev; netdev = alloc_etherdev(sizeof(struct nic_priv)); if (!netdev) { pr_err("%s(#%d): alloc dev failed", __func__, __LINE__); return NULL; } eth_hw_addr_random(netdev); netdev->netdev_ops = &nic_netdev_ops; /* keep the default flags, just add NOARP */ netdev->flags |= IFF_NOARP; /* There are no explicit users, so this is * now equivalent to NETIF_F_HW_CSUM. */ netdev->features |= NETIF_F_HW_CSUM; netdev->header_ops = &snull_header_ops; return netdev; } static int __init brook_init(void) { int ret; struct nic_priv *priv; nic_dev[0] = nic_alloc_netdev(); if (!nic_dev[0]) { pr_err("%s(#%d): alloc netdev[0] failed", __func__, __LINE__); return -ENOMEM; } nic_dev[1] = nic_alloc_netdev(); if (!nic_dev[1]) { pr_err("%s(#%d): alloc netdev[1] failed", __func__, __LINE__); ret = -ENOMEM; goto alloc_2nd_failed; } ret = register_netdev(nic_dev[0]); if (ret) { pr_err("%s(#%d): reg net driver failed. ret:%d", __func__, __LINE__, ret); goto reg1_failed; } ret = register_netdev(nic_dev[1]); if (ret) { pr_err("%s(#%d): reg net driver failed. ret:%d", __func__, __LINE__, ret); goto reg2_failed; } priv = netdev_priv(nic_dev[0]); priv->msg_enable = DEF_MSG_ENABLE; priv = netdev_priv(nic_dev[1]); priv->msg_enable = DEF_MSG_ENABLE; return 0; reg2_failed: unregister_netdev(nic_dev[0]); reg1_failed: free_netdev(nic_dev[1]); alloc_2nd_failed: free_netdev(nic_dev[0]); return ret; } module_init(brook_init); static void __exit brook_exit(void) { int i; pr_info("%s(#%d): remove module", __func__, __LINE__); for (i = 0; i < ARRAY_SIZE(nic_dev); i++) { unregister_netdev(nic_dev[i]); free_netdev(nic_dev[i]); } } module_exit(brook_exit);
brook@vista:~/oe-core$ tree meta/recipes-support/brook-cmake
meta/recipes-support/brook-cmake
|-- brook-cmake
| `-- brook-cmake.patch
`-- brook-cmake_1.0.bb
1 directory, 2 files
cmake_minimum_required (VERSION 2.6) project(brook-cmake-demo) add_executable(brook-cmake main.c) install(TARGETS brook-cmake DESTINATION bin)
#include <stdio.h> int main(int argc, char *argv[]) { printf("hello, cmake\n"); return 0; }
DESCRIPTION = "Brook CMake Project" LICENSE = "GPLv2" LIC_FILES_CHKSUM = "file://LICENSE;md5=5ff2bd2dd80c7cc542a6b8de3ee4ff87" SRC_URI = "file://brook-cmake.patch \ " inherit cmake EXTRA_OEMAKE = "-Wall"
brook@vista:~/oe-core/meta/recipes-support$ tree brook-cmake brook-cmake |-- brook-cmake-1.0 | `-- brook-cmake.patch |-- brook-cmake-2.0 | `-- brook-cmake.patch |-- brook-cmake_1.0.bb `-- brook-cmake_2.0.bb
brook@vista:~/oe-core$ cat meta/recipes-support/brook-cmake/brook-cmake_1.0.bb DESCRIPTION = "Brook CMake Project" LICENSE = "GPLv2" LIC_FILES_CHKSUM = "file://LICENSE;md5=7e4bf6f59b6da8e57ed5425a10a7310b" SRC_URI = "file://brook-cmake.patch \ " inherit cmake BBCLASSEXTEND = "native" EXTRA_OEMAKE = "-Wall" brook@vista:~/oe-core$ cat meta/recipes-support/brook-cmake/brook-cmake_2.0.bb DESCRIPTION = "Brook CMake Project" LICENSE = "GPLv2" LIC_FILES_CHKSUM = "file://LICENSE;md5=7e4bf6f59b6da8e57ed5425a10a7310b" SRC_URI = "file://brook-cmake.patch \ " inherit cmake BBCLASSEXTEND = "native" EXTRA_OEMAKE = "-Wall"
brook@vista:~/oe-core$ cat meta/recipes-support/brook-cmake/brook-cmake-1.0/brook-cmake.patch From 037c40faba39a11e54f282c3eab5e47a4cf1c7ca Mon Sep 17 00:00:00 2001 From: Brook <rene3210 at gmail.com> Date: Tue, 27 Sep 2016 20:42:11 +0800 Subject: [PATCH] brook oe demo code --- CMakeLists.txt | 5 +++++ LICENSE | 1 + main.c | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 main.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ee4d6d9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required (VERSION 2.6) +project(brook-cmake-demo) +add_executable(brook-cmake main.c) +install(TARGETS brook-cmake DESTINATION bin) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0664320 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +"GPLv2" diff --git a/main.c b/main.c new file mode 100644 index 0000000..d089aad --- /dev/null +++ b/main.c @@ -0,0 +1,8 @@ +#include+ +int main(int argc, char *argv[]) +{ + printf("hello, cmake 1.0\n"); + return 0; +} + -- 2.7.4 brook@vista:~/oe-core$ cat meta/recipes-support/brook-cmake/brook-cmake-2.0/brook-cmake.patch From 037c40faba39a11e54f282c3eab5e47a4cf1c7ca Mon Sep 17 00:00:00 2001 From: Brook <rene3210 at gmail.com> Date: Tue, 27 Sep 2016 20:42:11 +0800 Subject: [PATCH] brook oe demo code --- CMakeLists.txt | 5 +++++ LICENSE | 1 + main.c | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 main.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ee4d6d9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required (VERSION 2.6) +project(brook-cmake-demo) +add_executable(brook-cmake main.c) +install(TARGETS brook-cmake DESTINATION bin) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0664320 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +"GPLv2" diff --git a/main.c b/main.c new file mode 100644 index 0000000..d089aad --- /dev/null +++ b/main.c @@ -0,0 +1,8 @@ +#include + +int main(int argc, char *argv[]) +{ + printf("hello, cmake 2.0\n"); + return 0; +} + -- 2.7.4
brook@vista:~/oe-core$ grep -H PREFERRED_VERSION build/conf/local.conf build/conf/local.conf:PREFERRED_VERSION_brook-cmake = "1.0"相關資訊可以參考Bitbake User Manual/2.3. Preferences and Providers
include foo_no_exist.inc require foo_need_exist.inc
inherit autotools
INHERIT += sanity
# Sanity checks for common user misconfigurations
#
# See sanity.bbclass
#
# Expert users can confirm their sanity with "touch conf/sanity.conf"
BB_MIN_VERSION = "1.27.1"
SANITY_ABIFILE = "${TMPDIR}/abi_version"
SANITY_VERSION ?= "1"
LOCALCONF_VERSION ?= "1"
LAYER_CONF_VERSION ?= "6"
SITE_CONF_VERSION ?= "1"
INHERIT += "sanity"
int platform_device_register(struct platform_device *pdev) { device_initialize(&pdev->dev); arch_setup_pdev_archdata(pdev); return platform_device_add(pdev); } EXPORT_SYMBOL_GPL(platform_device_register); int platform_device_add(struct platform_device *pdev) { int i, ret; if (!pdev) return -EINVAL; if (!pdev->dev.parent) pdev->dev.parent = &platform_bus; pdev->dev.bus = &platform_bus_type; switch (pdev->id) { default: dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); break; case PLATFORM_DEVID_NONE: dev_set_name(&pdev->dev, "%s", pdev->name); break; case PLATFORM_DEVID_AUTO: /* * Automatically allocated device ID. We mark it as such so * that we remember it must be freed, and we append a suffix * to avoid namespace collision with explicit IDs. */ ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); if (ret < 0) goto err_out; pdev->id = ret; pdev->id_auto = true; dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id); break; } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; if (r->name == NULL) r->name = dev_name(&pdev->dev); p = r->parent; if (!p) { if (resource_type(r) == IORESOURCE_MEM) p = &iomem_resource; else if (resource_type(r) == IORESOURCE_IO) p = &ioport_resource; } if (p && insert_resource(p, r)) { dev_err(&pdev->dev, "failed to claim resource %d\n", i); ret = -EBUSY; goto failed; } } pr_debug("Registering platform device '%s'. Parent at %s\n", dev_name(&pdev->dev), dev_name(pdev->dev.parent)); ret = device_add(&pdev->dev); if (ret == 0) return ret; failed: if (pdev->id_auto) { ida_simple_remove(&platform_devid_ida, pdev->id); pdev->id = PLATFORM_DEVID_AUTO; } while (--i >= 0) { struct resource *r = &pdev->resource[i]; if (r->parent) release_resource(r); } err_out: return ret; } int device_add(struct device *dev) { struct device *parent = NULL; struct kobject *kobj; struct class_interface *class_intf; int error = -EINVAL; dev = get_device(dev); if (!dev) goto done; if (!dev->p) { error = device_private_init(dev); if (error) goto done; } /* * for statically allocated devices, which should all be converted * some day, we need to initialize the name. We prevent reading back * the name, and force the use of dev_name() */ if (dev->init_name) { dev_set_name(dev, "%s", dev->init_name); dev->init_name = NULL; } /* subsystems can specify simple device enumeration */ if (!dev_name(dev) && dev->bus && dev->bus->dev_name) dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); if (!dev_name(dev)) { error = -EINVAL; goto name_error; } pr_debug("device: '%s': %s\n", dev_name(dev), __func__); parent = get_device(dev->parent); kobj = get_device_parent(dev, parent); if (kobj) dev->kobj.parent = kobj; /* use parent numa_node */ if (parent) set_dev_node(dev, dev_to_node(parent)); /* first, register with generic layer. */ /* we require the name to be set before, and pass NULL */ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); if (error) goto Error; /* notify platform of device entry */ if (platform_notify) platform_notify(dev); error = device_create_file(dev, &dev_attr_uevent); if (error) goto attrError; error = device_add_class_symlinks(dev); if (error) goto SymlinkError; error = device_add_attrs(dev); if (error) goto AttrsError; error = bus_add_device(dev); if (error) goto BusError; error = dpm_sysfs_add(dev); if (error) goto DPMError; device_pm_add(dev); if (MAJOR(dev->devt)) { error = device_create_file(dev, &dev_attr_dev); if (error) goto DevAttrError; error = device_create_sys_dev_entry(dev); if (error) goto SysEntryError; devtmpfs_create_node(dev); } /* Notify clients of device addition. This call must come * after dpm_sysfs_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_ADD); bus_probe_device(dev); if (parent) klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children); if (dev->class) { mutex_lock(&dev->class->p->mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, &dev->class->p->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->mutex); } done: put_device(dev); return error; SysEntryError: if (MAJOR(dev->devt)) device_remove_file(dev, &dev_attr_dev); DevAttrError: device_pm_remove(dev); dpm_sysfs_remove(dev); DPMError: bus_remove_device(dev); BusError: device_remove_attrs(dev); AttrsError: device_remove_class_symlinks(dev); SymlinkError: device_remove_file(dev, &dev_attr_uevent); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: cleanup_device_parent(dev); put_device(parent); name_error: kfree(dev->p); dev->p = NULL; goto done; } void bus_probe_device(struct device *dev) { struct bus_type *bus = dev->bus; struct subsys_interface *sif; if (!bus) return; if (bus->p->drivers_autoprobe) device_initial_probe(dev); mutex_lock(&bus->p->mutex); list_for_each_entry(sif, &bus->p->interfaces, node) if (sif->add_dev) sif->add_dev(dev, sif); mutex_unlock(&bus->p->mutex); } void device_initial_probe(struct device *dev) { __device_attach(dev, true); } static int __device_attach(struct device *dev, bool allow_async) { int ret = 0; device_lock(dev); if (dev->driver) { if (klist_node_attached(&dev->p->knode_driver)) { ret = 1; goto out_unlock; } ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { struct device_attach_data data = { .dev = dev, .check_async = allow_async, .want_async = false, }; if (dev->parent) pm_runtime_get_sync(dev->parent); ret = bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); if (!ret && allow_async && data.have_async) { /* * If we could not find appropriate driver * synchronously and we are allowed to do * async probes and there are drivers that * want to probe asynchronously, we'll * try them. */ dev_dbg(dev, "scheduling asynchronous probe\n"); get_device(dev); async_schedule(__device_attach_async_helper, dev); } else { pm_request_idle(dev); } if (dev->parent) pm_runtime_put(dev->parent); } out_unlock: device_unlock(dev); return ret; } static int __device_attach_driver(struct device_driver *drv, void *_data) { struct device_attach_data *data = _data; struct device *dev = data->dev; bool async_allowed; /* * Check if device has already been claimed. This may * happen with driver loading, device discovery/registration, * and deferred probe processing happens all at once with * multiple threads. */ if (dev->driver) return -EBUSY; if (!driver_match_device(drv, dev)) return 0; async_allowed = driver_allows_async_probing(drv); if (async_allowed) data->have_async = true; if (data->check_async && async_allowed != data->want_async) return 0; return driver_probe_device(drv, dev); } static inline int driver_match_device(struct device_driver *drv, struct device *dev) { return drv->bus->match ? drv->bus->match(dev, drv) : 1; }
int platform_driver_register(struct platform_driver *drv) { drv->driver.bus = &platform_bus_type;/*关联总线*/ /*关联driver的设备方法*/ if (drv->probe) drv->driver.probe = platform_drv_probe; if (drv->remove) drv->driver.remove = platform_drv_remove; if (drv->shutdown) drv->driver.shutdown = platform_drv_shutdown; return driver_register(&drv->driver);/*注册驱动*/ } /******************************************************************************/ struct platform_driver { int (*probe)(struct platform_device *);/*匹配到设备后调用,下面分析内核代码怎么调用的*/ int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; }; struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .pm = &platform_dev_pm_ops, }; /********************************************************************************/ int driver_register(struct device_driver *drv) { int ret; struct device_driver *other; BUG_ON(!drv->bus->p); if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) printk(KERN_WARNING "Driver '%s' needs updating - please use " "bus_type methods\n", drv->name); other = driver_find(drv->name, drv->bus); if (other) { put_driver(other); printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting...\n", drv->name); return -EBUSY; } ret = bus_add_driver(drv); if (ret) return ret; ret = driver_add_groups(drv, drv->groups); if (ret) bus_remove_driver(drv); return ret; } int bus_add_driver(struct device_driver *drv) { struct bus_type *bus; struct driver_private *priv; int error = 0; bus = bus_get(drv->bus); if (!bus) return -EINVAL; pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { error = -ENOMEM; goto out_put_bus; } klist_init(&priv->klist_devices, NULL, NULL); priv->driver = drv; drv->p = priv; priv->kobj.kset = bus->p->drivers_kset; error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); if (error) goto out_unregister; if (drv->bus->p->drivers_autoprobe) { error = driver_attach(drv); if (error) goto out_unregister; } klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); module_add_driver(drv->owner, drv); error = driver_create_file(drv, &driver_attr_uevent); if (error) { printk(KERN_ERR "%s: uevent attr (%s) failed\n", __func__, drv->name); } error = driver_add_attrs(bus, drv); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", __func__, drv->name); } if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); if (error) { /* Ditto */ printk(KERN_ERR "%s: add_bind_files(%s) failed\n", __func__, drv->name); } } kobject_uevent(&priv->kobj, KOBJ_ADD); return 0; out_unregister: kobject_put(&priv->kobj); kfree(drv->p); drv->p = NULL; out_put_bus: bus_put(bus); return error; } int driver_attach(struct device_driver *drv) { /*对总线上的每一个设备都调用__driver_attach*/ return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); } static int __driver_attach(struct device *dev, void *data) { struct device_driver *drv = data; /* * Lock device and try to bind to it. We drop the error * here and always return 0, because we need to keep trying * to bind to devices and some drivers will return an error * simply if it didn't support the device. * * driver_probe_device() will spit a warning if there * is an error. */ if (!driver_match_device(drv, dev)) return 0; if (dev->parent) /* Needed for USB */ device_lock(dev->parent); device_lock(dev); if (!dev->driver) driver_probe_device(drv, dev); device_unlock(dev); if (dev->parent) device_unlock(dev->parent); return 0; } static inline int driver_match_device(struct device_driver *drv, struct device *dev) { /*调用总线的match去匹配设备和驱动*/ return drv->bus->match ? drv->bus->match(dev, drv) : 1; } int driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; if (!device_is_registered(dev)) return -ENODEV; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); pm_runtime_get_noresume(dev); pm_runtime_barrier(dev); ret = really_probe(dev, drv); pm_runtime_put_sync(dev); return ret; } static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; } /**********************************************************************************/ if (dev->bus->probe) {/*首先看总线有没有probe函数,若有则调用,而平台总线没有probe*/ ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) {/*然后看驱动有没有probe函数,若有则调用,*/ ret = drv->probe(dev); if (ret) goto probe_failed; } /************************************************************************************/ driver_bound(dev); ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done; probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); } /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0; done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret; } /*平台总线的match逻辑*/ static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); /* match against the id table first */ if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0);/*驱动名字与设备名字要匹配*/ }
#include <linux/module.h> #include <linux/platform_device.h> MODULE_AUTHOR("Brook"); MODULE_DESCRIPTION("Kernel module for demo"); MODULE_LICENSE("GPL"); #define DEVNAME "brook" #define DYN_ALLOC 1 static struct platform_device brook_device = { .name = DEVNAME, }; static int brook_probe(struct platform_device *pdev) { pr_info("%s(#%d)\n", __func__, __LINE__); return 0; } static int brook_remove(struct platform_device *pdev) { pr_info("%s(#%d)\n", __func__, __LINE__); return 0; } static struct platform_driver brook_driver = { .driver = { .name = DEVNAME, .owner = THIS_MODULE, }, .probe = brook_probe, .remove = brook_remove, }; static int __init brook_init(void) { int err; pr_info("%s(#%d)\n", __func__, __LINE__); err = platform_device_register(&brook_device); if (err) { pr_err("%s(#%d): platform_device_register failed(%d)\n", __func__, __LINE__, err); return err; } err = platform_driver_register(&brook_driver); if (err) { dev_err(&(brook_device.dev), "%s(#%d): platform_driver_register fail(%d)\n", __func__, __LINE__, err); goto dev_reg_failed; } return err; dev_reg_failed: platform_device_unregister(&brook_device); return err; } module_init(brook_init); static void __exit brook_exit(void) { dev_info(&(brook_device.dev), "%s(#%d)\n", __func__, __LINE__); platform_device_unregister(&brook_device); platform_driver_unregister(&brook_driver); } module_exit(brook_exit);
#include <linux/module.h> #include <linux/platform_device.h> MODULE_AUTHOR("Brook"); MODULE_DESCRIPTION("Kernel module for demo"); MODULE_LICENSE("GPL"); #define DEVNAME "brook" #define DYN_ALLOC 1 static struct platform_device *brook_device; static int brook_probe(struct platform_device *pdev) { pr_info("%s(#%d)\n", __func__, __LINE__); return 0; } static int brook_remove(struct platform_device *pdev) { pr_info("%s(#%d)\n", __func__, __LINE__); return 0; } static struct platform_driver brook_driver = { .driver = { .name = DEVNAME, .owner = THIS_MODULE, }, .probe = brook_probe, .remove = brook_remove, }; static int __init brook_init(void) { int err; pr_info("%s(#%d)\n", __func__, __LINE__); /* using platform_device_alloc() + platform_device_add() * instead of platform_device_register() to avoid the OOPS, * "Device 'brook.0' does not have a release() function, * it is broken and must be fixed." */ brook_device = platform_device_alloc(DEVNAME, 0); if (!brook_device) { pr_err("%s(#%d): platform_device_alloc fail\n", __func__, __LINE__); return -ENOMEM; } err = platform_device_add(brook_device); if (err) { pr_err("%s(#%d): platform_device_add failed\n", __func__, __LINE__); goto dev_add_failed; } err = platform_driver_register(&brook_driver); if (err) { dev_err(&(brook_device->dev), "%s(#%d): platform_driver_register fail(%d)\n", __func__, __LINE__, err); goto dev_reg_failed; } return err; dev_add_failed: platform_device_put(brook_device); dev_reg_failed: platform_device_unregister(brook_device); return err; } module_init(brook_init); static void __exit brook_exit(void) { dev_info(&(brook_device->dev), "%s(#%d)\n", __func__, __LINE__); platform_device_unregister(brook_device); platform_driver_unregister(&brook_driver); } module_exit(brook_exit);
brook@vista:/home/brook/oe/oe-core/build$ bitbake -v meta-toolchain ... + chmod +x /home/brook/oe/oe-core/build/tmp-eglibc/deploy/sdk/oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.sh + cat /home/brook/oe/oe-core/build/tmp-eglibc/deploy/sdk/oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.tar.bz2 + rm /home/brook/oe/oe-core/build/tmp-eglibc/deploy/sdk/oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.tar.bz2 NOTE: Tasks Summary: Attempted 1685 tasks of which 1312 didn't need to be rerun and all succeeded. brook@vista:/home/brook/oe/oe-core/build$ tree tmp-eglibc/deploy/sdk/ tmp-eglibc/deploy/sdk/ `-- oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.sh 0 directories, 1 file
brook@vista:/home/brook/oe/oe-core/build$ ./tmp-eglibc/deploy/sdk/oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.sh --help Usage: oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.sh [-y] [-d <dir>] -y Automatic yes to all prompts -d <dir> Install the SDK to <dir> ======== Advanced DEBUGGING ONLY OPTIONS ======== -S Save relocation scripts -R Do not relocate executables -D use set -x to see what is going on brook@vista:~$ /home/brook/oe/oe-core/build/tmp-eglibc/deploy/sdk/oecore-x86_64-armv7a-vfp-neon-toolchain-oe-core.0.sh -d /opt/oe -D + printf 'Enter target directory for SDK (default: /usr/local/oecore-x86_64): ' Enter target directory for SDK (default: /usr/local/oecore-x86_64): + '[' /opt/oe = '' ']' + echo /opt/oe /opt/oe ... + '[' 0 = 0 ']' + /usr/bin/sudo rm /SSD/opt/oe/relocate_sdk.py /SSD/opt/oe/relocate_sdk.sh + echo 'SDK has been successfully set up and is ready to be used.' SDK has been successfully set up and is ready to be used. + exit 0
export PATH=/SSD/opt/oe/sysroots/x86_64-oesdk-linux/usr/bin:/SSD/opt/oe/sysroots/x86_64-oesdk-linux/usr/bin/armv 7a-vfp-neon-oe-linux-gnueabi:$PATH export PKG_CONFIG_SYSROOT_DIR=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi export PKG_CONFIG_PATH=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi/usr/lib/pkgconfig export CONFIG_SITE=/SSD/opt/oe/site-config-armv7a-vfp-neon-oe-linux-gnueabi export CC="arm-oe-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mthumb-inte rwork --sysroot=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export CXX="arm-oe-linux-gnueabi-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mthumb-int erwork --sysroot=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export CPP="arm-oe-linux-gnueabi-gcc -E -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mthumb-interwork --sysroot=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export AS="arm-oe-linux-gnueabi-as " export LD="arm-oe-linux-gnueabi-ld --sysroot=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export GDB=arm-oe-linux-gnueabi-gdb export STRIP=arm-oe-linux-gnueabi-strip export RANLIB=arm-oe-linux-gnueabi-ranlib export OBJCOPY=arm-oe-linux-gnueabi-objcopy export OBJDUMP=arm-oe-linux-gnueabi-objdump export AR=arm-oe-linux-gnueabi-ar export NM=arm-oe-linux-gnueabi-nm export M4=m4 export TARGET_PREFIX=arm-oe-linux-gnueabi- export CONFIGURE_FLAGS="--target=arm-oe-linux-gnueabi --host=arm-oe-linux-gnueabi --build=x86_64-linux --with-libtool-sysroot=/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export CFLAGS=" -O2 -fexpensive-optimizations -frename-registers -fomit-frame-pointer" export CXXFLAGS=" -O2 -fexpensive-optimizations -frename-registers -fomit-frame-pointer -fpermissive" export LDFLAGS="-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed" export CPPFLAGS="" export OECORE_NATIVE_SYSROOT="/SSD/opt/oe/sysroots/x86_64-oesdk-linux" export OECORE_TARGET_SYSROOT="/SSD/opt/oe/sysroots/armv7a-vfp-neon-oe-linux-gnueabi" export OECORE_ACLOCAL_OPTS="-I /SSD/opt/oe/sysroots/x86_64-oesdk-linux/usr/share/aclocal" export OECORE_DISTRO_VERSION="20151225" export OECORE_SDK_VERSION="oe-core.0" export PYTHONHOME=/SSD/opt/oe/sysroots/x86_64-oesdk-linux/usr export ARCH=arm export CROSS_COMPILE=arm-oe-linux-gnueabi-
brook@vista:~$ source /opt/oe/environment-setup-armv7a-vfp-neon-oe-linux-gnueabi
brook@vista:~$ cat main.c
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello\n");
return 0;
}
brook@vista:~$ $CC -o brook-sdk main.c
D:\Projects>adb push z:\brook-sdk /
688 KB/s (5644 bytes in 0.008s)
D:\Projects>adb shell chmod +x /brook-sdk
D:\Projects>adb shell /brook-sdk
hello
inherit module
DESCRIPTION = "Brook Out Tree Kernel Module"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://LICENSE;md5=5ff2bd2dd80c7cc542a6b8de3ee4ff87"
PR = "r1-${KERNEL_VERSION}"
# This DEPENDS is to serialize kernel module builds
DEPENDS = "virtual/kernel"
SRC_URI = "file://brook.patch \
"
S = "${WORKDIR}/brook-linux-${PV}"
/oe-core/meta/recipes-kernel/brook
|-- brook_1.0.bb
|-- files
| `-- brook.patch
`-- git
|-- LICENSE
|-- Makefile
`-- main.c
ifneq ($(KERNELRELEASE),) # obj-m := <module_name>.o # <module_name>-y := <src1>.o <src2>.o ... EXTRA_CFLAGS += -DYAFFS_OUT_OF_TREE obj-m := brook.o brook-objs := main.o else PWD := $(shell pwd) modules: $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install clean: $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean endif
#include <linux/module.h> MODULE_AUTHOR("Brook"); MODULE_DESCRIPTION("Kernel module for demo"); MODULE_LICENSE("GPL"); static int __init brook_init(void) { printk(KERN_INFO "Brook Module Init\n"); return 0; } module_init(brook_init); static void __exit brook_exit(void) { printk(KERN_INFO "Brook Module Exit\n"); return; } module_exit(brook_exit);