【无标题】ethtool程序,从用户态调用内核态的对照分析

2023-10-12 18:12

本文主要是介绍【无标题】ethtool程序,从用户态调用内核态的对照分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

# 1. 说明

- 用户层ethtool使用的是: ethtool-6.5 为例,下载来自:

https://mirrors.edge.kernel.org/pub/software/network/ethtool/

- 内核层:在内核源码中,VSCode -->【ctrl+p】搜索文件:linux/ethtool.h及    core/ethtool.c,相关实现在这两个文件中。

# 2. 应用层 ethtool-6.5

- ethtool.c  

下面的 args 结构体展示了成员的选项(.opts)、执行函数(.func)、netlink执行函数(.nlfunc,暂时不必关心)、帮助(.xhelp)。  

通过他们,能看出ethtool命令行后面跟什么选项时,调用了什么函数!

```c++

//

static const struct option args[] = {

    {

        /* "default" entry when no switch is used */

        .opts   = "",

        .func   = do_gset,

        .nlfunc = nl_gset,

        .help   = "Display standard information about device",

    },

    {

        .opts   = "-s|--change",

        .func   = do_sset,

        .nlfunc = nl_sset,

        .help   = "Change generic options",

        .xhelp  = "     [ speed %d ]\n"

              "     [ lanes %d ]\n"

              "     [ duplex half|full ]\n"

              "     [ port tp|aui|bnc|mii|fibre|da ]\n"

              "     [ mdix auto|on|off ]\n"

              "     [ autoneg on|off ]\n"

              "     [ advertise %x[/%x] | mode on|off ... [--] ]\n"

              "     [ phyad %d ]\n"

              "     [ xcvr internal|external ]\n"

              "     [ wol %d[/%d] | p|u|m|b|a|g|s|f|d... ]\n"

              "     [ sopass %x:%x:%x:%x:%x:%x ]\n"

              "     [ msglvl %d[/%d] | type on|off ... [--] ]\n"

              "     [ master-slave preferred-master|preferred-slave|forced-master|forced-slave ]\n"

    },

    {

        .opts   = "-a|--show-pause",

        .json   = true,

        .func   = do_gpause,

        .nlfunc = nl_gpause,

        .help   = "Show pause options",

        .xhelp  = "     [ --src aggregate | emac | pmac ]\n"

    },

    {

        .opts   = "-A|--pause",

        .func   = do_spause,

        .nlfunc = nl_spause,

        .help   = "Set pause options",

        .xhelp  = "     [ autoneg on|off ]\n"

              "     [ rx on|off ]\n"

              "     [ tx on|off ]\n"

    },

    {

        .opts   = "-c|--show-coalesce",

        .json   = true,

        .func   = do_gcoalesce,

        .nlfunc = nl_gcoalesce,

        .help   = "Show coalesce options"

    },

    {

        .opts   = "-C|--coalesce",

        .func   = do_scoalesce,

        .nlfunc = nl_scoalesce,

        .help   = "Set coalesce options",

        .xhelp  = "     [adaptive-rx on|off]\n"

              "     [adaptive-tx on|off]\n"

              "     [rx-usecs N]\n"

              "     [rx-frames N]\n"

              "     [rx-usecs-irq N]\n"

              "     [rx-frames-irq N]\n"

              "     [tx-usecs N]\n"

              "     [tx-frames N]\n"

              "     [tx-usecs-irq N]\n"

              "     [tx-frames-irq N]\n"

              "     [stats-block-usecs N]\n"

              "     [pkt-rate-low N]\n"

              "     [rx-usecs-low N]\n"

              "     [rx-frames-low N]\n"

              "     [tx-usecs-low N]\n"

              "     [tx-frames-low N]\n"

              "     [pkt-rate-high N]\n"

              "     [rx-usecs-high N]\n"

              "     [rx-frames-high N]\n"

              "     [tx-usecs-high N]\n"

              "     [tx-frames-high N]\n"

              "     [sample-interval N]\n"

              "     [cqe-mode-rx on|off]\n"

              "     [cqe-mode-tx on|off]\n"

              "     [tx-aggr-max-bytes N]\n"

              "     [tx-aggr-max-frames N]\n"

              "     [tx-aggr-time-usecs N]\n"

    },

    {

        .opts   = "-g|--show-ring",

        .json   = true,

        .func   = do_gring,

        .nlfunc = nl_gring,

        .help   = "Query RX/TX ring parameters"

    },

    {

        .opts   = "-G|--set-ring",

        .func   = do_sring,

        .nlfunc = nl_sring,

        .help   = "Set RX/TX ring parameters",

        .xhelp  = "     [ rx N ]\n"

              "     [ rx-mini N ]\n"

              "     [ rx-jumbo N ]\n"

              "     [ tx N ]\n"

              "     [ rx-buf-len N ]\n"

              "     [ cqe-size N ]\n"

              "     [ tx-push on|off ]\n"

              "     [ rx-push on|off ]\n"

              "     [ tx-push-buf-len N]\n"

    },

    {

        .opts   = "-k|--show-features|--show-offload",

        .json   = true,

        .func   = do_gfeatures,

        .nlfunc = nl_gfeatures,

        .help   = "Get state of protocol offload and other features"

    },

    {

        .opts   = "-K|--features|--offload",

        .func   = do_sfeatures,

        .nlfunc = nl_sfeatures,

        .help   = "Set protocol offload and other features",

        .xhelp  = "     FEATURE on|off ...\n"

    },

    {

        .opts   = "-i|--driver",

        .func   = do_gdrv,

        .help   = "Show driver information"

    },

    {

        .opts   = "-d|--register-dump",

        .func   = do_gregs,

        .help   = "Do a register dump",

        .xhelp  = "     [ raw on|off ]\n"

              "     [ file FILENAME ]\n"

    },

    {

        .opts   = "-e|--eeprom-dump",

        .func   = do_geeprom,

        .help   = "Do a EEPROM dump",

        .xhelp  = "     [ raw on|off ]\n"

              "     [ offset N ]\n"

              "     [ length N ]\n"

    },

    {

        .opts   = "-E|--change-eeprom",

        .func   = do_seeprom,

        .help   = "Change bytes in device EEPROM",

        .xhelp  = "     [ magic N ]\n"

              "     [ offset N ]\n"

              "     [ length N ]\n"

              "     [ value N ]\n"

    },

    {

        .opts   = "-r|--negotiate",

        .func   = do_nway_rst,

        .help   = "Restart N-WAY negotiation"

    },

    {

        .opts   = "-p|--identify",

        .func   = do_phys_id,

        .help   = "Show visible port identification (e.g. blinking)",

        .xhelp  = "     [ TIME-IN-SECONDS ]\n"

    },

    {

        .opts   = "-t|--test",

        .func   = do_test,

        .help   = "Execute adapter self test",

        .xhelp  = "     [ online | offline | external_lb ]\n"

    },

    {

        .opts   = "-S|--statistics",

        .json   = true,

        .func   = do_gnicstats,

        .nlchk  = nl_gstats_chk,

        .nlfunc = nl_gstats,

        .help   = "Show adapter statistics",

        .xhelp  = "     [ --all-groups | --groups [eth-phy] [eth-mac] [eth-ctrl] [rmon] ]\n"

              "     [ --src aggregate | emac | pmac ]\n"

    },

    {

        .opts   = "--phy-statistics",

        .func   = do_gphystats,

        .help   = "Show phy statistics"

    },

    {

        .opts   = "-n|-u|--show-nfc|--show-ntuple",

        .func   = do_grxclass,

        .help   = "Show Rx network flow classification options or rules",

        .xhelp  = "     [ rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|"

              "tcp6|udp6|ah6|esp6|sctp6 [context %d] |\n"

              "       rule %d ]\n"

    },

    {

        .opts   = "-N|-U|--config-nfc|--config-ntuple",

        .func   = do_srxclass,

        .help   = "Configure Rx network flow classification options or rules",

        .xhelp  = "     rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|"

              "tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... [context %d] |\n"

              "     flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4|"

              "ip6|tcp6|udp6|ah6|esp6|sctp6\n"

              "         [ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"

              "         [ dst %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"

              "         [ proto %d [m %x] ]\n"

              "         [ src-ip IP-ADDRESS [m IP-ADDRESS] ]\n"

              "         [ dst-ip IP-ADDRESS [m IP-ADDRESS] ]\n"

              "         [ tos %d [m %x] ]\n"

              "         [ tclass %d [m %x] ]\n"

              "         [ l4proto %d [m %x] ]\n"

              "         [ src-port %d [m %x] ]\n"

              "         [ dst-port %d [m %x] ]\n"

              "         [ spi %d [m %x] ]\n"

              "         [ vlan-etype %x [m %x] ]\n"

              "         [ vlan %x [m %x] ]\n"

              "         [ user-def %x [m %x] ]\n"

              "         [ dst-mac %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"

              "         [ action %d ] | [ vf %d queue %d ]\n"

              "         [ context %d ]\n"

              "         [ loc %d ] |\n"

              "     delete %d\n"

    },

    {

        .opts   = "-T|--show-time-stamping",

        .func   = do_tsinfo,

        .nlfunc = nl_tsinfo,

        .help   = "Show time stamping capabilities"

    },

    {

        .opts   = "-x|--show-rxfh-indir|--show-rxfh",

        .json   = true,

        .func   = do_grxfh,

        .nlfunc = nl_grss,

        .help   = "Show Rx flow hash indirection table and/or RSS hash key",

        .xhelp  = "     [ context %d ]\n"

    },

    {

        .opts   = "-X|--set-rxfh-indir|--rxfh",

        .func   = do_srxfh,

        .help   = "Set Rx flow hash indirection table and/or RSS hash key",

        .xhelp  = "     [ context %d|new ]\n"

              "     [ equal N | weight W0 W1 ... | default ]\n"

              "     [ hkey %x:%x:%x:%x:%x:.... ]\n"

              "     [ hfunc FUNC ]\n"

              "     [ delete ]\n"

    },

    {

        .opts   = "-f|--flash",

        .func   = do_flash,

        .help   = "Flash firmware image from the specified file to a region on the device",

        .xhelp  = "     FILENAME [ REGION-NUMBER-TO-FLASH ]\n"

    },

    {

        .opts   = "-P|--show-permaddr",

        .func   = do_permaddr,

        .nlfunc = nl_permaddr,

        .help   = "Show permanent hardware address"

    },

    {

        .opts   = "-w|--get-dump",

        .func   = do_getfwdump,

        .help   = "Get dump flag, data",

        .xhelp  = "     [ data FILENAME ]\n"

    },

    {

        .opts   = "-W|--set-dump",

        .func   = do_setfwdump,

        .help   = "Set dump flag of the device",

        .xhelp  = "     N\n"

    },

    {

        .opts   = "-l|--show-channels",

        .func   = do_gchannels,

        .nlfunc = nl_gchannels,

        .help   = "Query Channels"

    },

    {

        .opts   = "-L|--set-channels",

        .func   = do_schannels,

        .nlfunc = nl_schannels,

        .help   = "Set Channels",

        .xhelp  = "     [ rx N ]\n"

              "     [ tx N ]\n"

              "     [ other N ]\n"

              "     [ combined N ]\n"

    },

    {

        .opts   = "--show-priv-flags",

        .func   = do_gprivflags,

        .nlfunc = nl_gprivflags,

        .help   = "Query private flags"

    },

    {

        .opts   = "--set-priv-flags",

        .func   = do_sprivflags,

        .nlfunc = nl_sprivflags,

        .help   = "Set private flags",

        .xhelp  = "     FLAG on|off ...\n"

    },

    {

        .opts   = "-m|--dump-module-eeprom|--module-info",

        .func   = do_getmodule,

        .nlfunc = nl_getmodule,

        .help   = "Query/Decode Module EEPROM information and optical diagnostics if available",

        .xhelp  = "     [ raw on|off ]\n"

              "     [ hex on|off ]\n"

              "     [ offset N ]\n"

              "     [ length N ]\n"

              "     [ page N ]\n"

              "     [ bank N ]\n"

              "     [ i2c N ]\n"

    },

    {

        .opts   = "--show-eee",

        .func   = do_geee,

        .nlfunc = nl_geee,

        .help   = "Show EEE settings",

    },

    {

        .opts   = "--set-eee",

        .func   = do_seee,

        .nlfunc = nl_seee,

        .help   = "Set EEE settings",

        .xhelp  = "     [ eee on|off ]\n"

              "     [ advertise %x ]\n"

              "     [ tx-lpi on|off ]\n"

              "     [ tx-timer %d ]\n"

    },

    {

        .opts   = "--set-phy-tunable",

        .func   = do_set_phy_tunable,

        .help   = "Set PHY tunable",

        .xhelp  = "     [ downshift on|off [count N] ]\n"

              "     [ fast-link-down on|off [msecs N] ]\n"

              "     [ energy-detect-power-down on|off [msecs N] ]\n"

    },

    {

        .opts   = "--get-phy-tunable",

        .func   = do_get_phy_tunable,

        .help   = "Get PHY tunable",

        .xhelp  = "     [ downshift ]\n"

              "     [ fast-link-down ]\n"

              "     [ energy-detect-power-down ]\n"

    },

    {

        .opts   = "--get-tunable",

        .func   = do_gtunable,

        .help   = "Get tunable",

        .xhelp  = "     [ rx-copybreak ]\n"

              "     [ tx-copybreak ]\n"

              "     [ tx-buf-size ]\n"

              "     [ pfc-prevention-tout ]\n"

    },

    {

        .opts   = "--set-tunable",

        .func   = do_stunable,

        .help   = "Set tunable",

        .xhelp  = "     [ rx-copybreak N ]\n"

              "     [ tx-copybreak N ]\n"

              "     [ tx-buf-size N ]\n"

              "     [ pfc-prevention-tout N ]\n"

    },

    {

        .opts   = "--reset",

        .func   = do_reset,

        .help   = "Reset components",

        .xhelp  = "     [ flags %x ]\n"

              "     [ mgmt ]\n"

              "     [ mgmt-shared ]\n"

              "     [ irq ]\n"

              "     [ irq-shared ]\n"

              "     [ dma ]\n"

              "     [ dma-shared ]\n"

              "     [ filter ]\n"

              "     [ filter-shared ]\n"

              "     [ offload ]\n"

              "     [ offload-shared ]\n"

              "     [ mac ]\n"

              "     [ mac-shared ]\n"

              "     [ phy ]\n"

              "     [ phy-shared ]\n"

              "     [ ram ]\n"

              "     [ ram-shared ]\n"

              "     [ ap ]\n"

              "     [ ap-shared ]\n"

              "     [ dedicated ]\n"

              "     [ all ]\n"

    },

    {

        .opts   = "--show-fec",

        .json   = true,

        .func   = do_gfec,

        .nlfunc = nl_gfec,

        .help   = "Show FEC settings",

    },

    {

        .opts   = "--set-fec",

        .func   = do_sfec,

        .nlfunc = nl_sfec,

        .help   = "Set FEC settings",

        .xhelp  = "     [ encoding auto|off|rs|baser|llrs [...] ]\n"

    },

    {

        .opts   = "-Q|--per-queue",

        .func   = do_perqueue,

        .help   = "Apply per-queue command. ",

        .xhelp  = "The supported sub commands include --show-coalesce, --coalesce"

              "     [queue_mask %x] SUB_COMMAND\n",

    },

    {

        .opts   = "--cable-test",

        .json   = true,

        .nlfunc = nl_cable_test,

        .help   = "Perform a cable test",

    },

    {

        .opts   = "--cable-test-tdr",

        .json   = true,

        .nlfunc = nl_cable_test_tdr,

        .help   = "Print cable test time domain reflectrometery data",

        .xhelp  = "     [ first N ]\n"

              "     [ last N ]\n"

              "     [ step N ]\n"

              "     [ pair N ]\n"

    },

    {

        .opts   = "--show-tunnels",

        .nlfunc = nl_gtunnels,

        .help   = "Show NIC tunnel offload information",

    },

    {

        .opts   = "--show-module",

        .json   = true,

        .nlfunc = nl_gmodule,

        .help   = "Show transceiver module settings",

    },

    {

        .opts   = "--set-module",

        .nlfunc = nl_smodule,

        .help   = "Set transceiver module settings",

        .xhelp  = "     [ power-mode-policy high|auto ]\n"

    },

    {

        .opts   = "--get-plca-cfg",

        .nlfunc = nl_plca_get_cfg,

        .help   = "Get PLCA configuration",

    },

    {

        .opts   = "--set-plca-cfg",

        .nlfunc = nl_plca_set_cfg,

        .help   = "Set PLCA configuration",

        .xhelp  = "     [ enable on|off ]\n"

              "     [ node-id N ]\n"

              "     [ node-cnt N ]\n"

              "     [ to-tmr N ]\n"

              "     [ burst-cnt N ]\n"

              "     [ burst-tmr N ]\n"

    },

    {

        .opts   = "--get-plca-status",

        .nlfunc = nl_plca_get_status,

        .help   = "Get PLCA status information",

    },

    {

        .opts   = "--show-mm",

        .json   = true,

        .nlfunc = nl_get_mm,

        .help   = "Show MAC merge layer state",

    },

    {

        .opts   = "--set-mm",

        .nlfunc = nl_set_mm,

        .help   = "Set MAC merge layer parameters",

              "     [ verify-enabled on|off ]\n"

              "     [ verify-time N ]\n"

              "     [ tx-enabled on|off ]\n"

              "     [ pmac-enabled on|off ]\n"

              "     [ tx-min-frag-size 60-252 ]\n"

    },

    {

        .opts   = "--show-pse",

        .json   = true,

        .nlfunc = nl_gpse,

        .help   = "Show settings for Power Sourcing Equipment",

    },

    {

        .opts   = "--set-pse",

        .nlfunc = nl_spse,

        .help   = "Set Power Sourcing Equipment settings",

        .xhelp  = "     [ podl-pse-admin-control enable|disable ]\n"

    },

    {

        .opts   = "-h|--help",

        .no_dev = true,

        .func   = show_usage,

        .help   = "Show this help"

    },

    {

        .opts   = "--version",

        .no_dev = true,

        .func   = do_version,

        .help   = "Show version number"

    },

    {}

};


 

```

## 读操作

这里以 .opts   = "-i|--driver" 为例:读取网卡信息

```shell

#使用:ethtool -i ethX

do_gdrv

    --> send_ioctl(ETHTOOL_GDRVINFO)

        --> ioctl(SIOCETHTOOL);

```

## 写操作

这里以 .opts   = "-p|--identify"为例,设置网卡点灯时间

```shell

#使用:ethtool -p ethX 10

do_phys_id

    --> send_ioctl(ETHTOOL_PHYS_ID);

        --> ioctl(SIOCETHTOOL);

```

应用层调用到 ioctl ,到此为止!

# 3. 内核层

继续上面示例,应用层 ioctl 继续调用内核层 dev_ioctl:

## 读操作:读取网卡信息

```shell

dev_ioctl case SIOCETHTOOL:-->

    --> dev_ethtool

        --> ethtool_get_drvinfo

            --> ops->get_drvinfo  #这个函数是 struct ethtool_ops 结构体中,需要自己实现

```

## 写操作:设置网卡点灯时间

```shell

dev_ioctl case SIOCETHTOOL:-->

    --> dev_ethtool

        --> ethtool_phys_id

            --> ops->set_phys_id  #这个函数是 struct ethtool_ops 结构体中,需要自己实现

```

## struct ethtool_ops 内容(linux/ethtool.h)

```c++

struct ethtool_ops {

 {

    int (*get_settings)(struct net_device *, struct ethtool_cmd *);

    int (*set_settings)(struct net_device *, struct ethtool_cmd *);

    void    (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);

    int (*get_regs_len)(struct net_device *);

    void    (*get_regs)(struct net_device *, struct ethtool_regs *, void *);

    void    (*get_wol)(struct net_device *, struct ethtool_wolinfo *);

    int (*set_wol)(struct net_device *, struct ethtool_wolinfo *);

    u32 (*get_msglevel)(struct net_device *);

    void    (*set_msglevel)(struct net_device *, u32);

    int (*nway_reset)(struct net_device *);

    u32 (*get_link)(struct net_device *);

    int (*get_eeprom_len)(struct net_device *);

    int (*get_eeprom)(struct net_device *,

                  struct ethtool_eeprom *, u8 *);

    int (*set_eeprom)(struct net_device *,

                  struct ethtool_eeprom *, u8 *);

    int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);

    int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);

    void    (*get_ringparam)(struct net_device *,

                 struct ethtool_ringparam *);

    int (*set_ringparam)(struct net_device *,

                 struct ethtool_ringparam *);

    void    (*get_pauseparam)(struct net_device *,

                  struct ethtool_pauseparam*);

    int (*set_pauseparam)(struct net_device *,

                  struct ethtool_pauseparam*);

    void    (*self_test)(struct net_device *, struct ethtool_test *, u64 *);

    void    (*get_strings)(struct net_device *, u32 stringset, u8 *);

    int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);

    void    (*get_ethtool_stats)(struct net_device *,

                     struct ethtool_stats *, u64 *);

    int (*begin)(struct net_device *);

    void    (*complete)(struct net_device *);

    u32 (*get_priv_flags)(struct net_device *);

    int (*set_priv_flags)(struct net_device *, u32);

    int (*get_sset_count)(struct net_device *, int);

    int (*get_rxnfc)(struct net_device *,

                 struct ethtool_rxnfc *, u32 *rule_locs);

    int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);

    int (*flash_device)(struct net_device *, struct ethtool_flash *);

    int (*reset)(struct net_device *, u32 *);

    u32 (*get_rxfh_key_size)(struct net_device *);

    u32 (*get_rxfh_indir_size)(struct net_device *);

    int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key,

                u8 *hfunc);

    int (*set_rxfh)(struct net_device *, const u32 *indir,

                const u8 *key, const u8 hfunc);

    void    (*get_channels)(struct net_device *, struct ethtool_channels *);

    int (*set_channels)(struct net_device *, struct ethtool_channels *);

    int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);

    int (*get_dump_data)(struct net_device *,

                 struct ethtool_dump *, void *);

    int (*set_dump)(struct net_device *, struct ethtool_dump *);

    int (*get_ts_info)(struct net_device *, struct ethtool_ts_info *);

    int     (*get_module_info)(struct net_device *,

                   struct ethtool_modinfo *);

    int     (*get_module_eeprom)(struct net_device *,

                     struct ethtool_eeprom *, u8 *);

    int (*get_eee)(struct net_device *, struct ethtool_eee *);

    int (*set_eee)(struct net_device *, struct ethtool_eee *);

    int (*get_tunable)(struct net_device *,

                   const struct ethtool_tunable *, void *);

    int (*set_tunable)(struct net_device *,

                   const struct ethtool_tunable *, const void *);


 

};

```

## ethtool_ops使用的典型参考:dm9000.c

在内核源码中,VScode--【ctrl+p】,输入 dm9000.c

```c++

static const struct ethtool_ops dm9000_ethtool_ops = {

    .get_drvinfo        = dm9000_get_drvinfo,

    .get_settings       = dm9000_get_settings,

    .set_settings       = dm9000_set_settings,

    .get_msglevel       = dm9000_get_msglevel,

    .set_msglevel       = dm9000_set_msglevel,

    .nway_reset     = dm9000_nway_reset,

    .get_link       = dm9000_get_link,

    .get_wol        = dm9000_get_wol,

    .set_wol        = dm9000_set_wol,

    .get_eeprom_len     = dm9000_get_eeprom_len,

    .get_eeprom     = dm9000_get_eeprom,

    .set_eeprom     = dm9000_set_eeprom,

};

```


 

这篇关于【无标题】ethtool程序,从用户态调用内核态的对照分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/197577

相关文章

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

美容美发店营销版微信小程序源码

打造线上生意新篇章 一、引言:微信小程序,开启美容美发行业新纪元 在数字化时代,微信小程序以其便捷、高效的特点,成为了美容美发行业营销的新宠。本文将带您深入了解美容美发营销微信小程序,探讨其独特优势及如何助力商家实现业务增长。 二、微信小程序:美容美发行业的得力助手 拓宽客源渠道:微信小程序基于微信社交平台,轻松实现线上线下融合,帮助商家快速吸引潜在客户,拓宽客源渠道。 提升用户体验:

程序人生--拔丝地瓜

一个会享受生活的人,难免会执迷于探索“三餐茶饭,四季衣裳”的朴素涵义。如今在这繁杂喧闹、竞争激烈的社会环境里,如何才能从周而复始的生活中挖掘出一点儿期待!这是一个仁者见仁智者见智的开放性话题。对于大部分的人来说,看电影、运动、旅游、美食、加班....是假日的备选安排。 春节临走之前,再次尝试“拔丝地瓜”,为何要强调“再次”二字?因为这道甜菜我已经尝试过很多次,失败与成功都经历过。十几年的烧饭经历

ScrollView 非手动调用的方法

1. /**  *  非人为的时候调用这个方法  *  *  @param scrollView <#scrollView description#>  */ - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {           } 2.判断控制器的view是否加载过 [willShowVC

打包体积分析和优化

webpack分析工具:webpack-bundle-analyzer 1. 通过<script src="./vue.js"></script>方式引入vue、vuex、vue-router等包(CDN) // webpack.config.jsif(process.env.NODE_ENV==='production') {module.exports = {devtool: 'none