热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

(others)ICMP报文详解系列

Linuxicmp学习笔记之一icmp协议相关的格式分类:linux网络2014-04-1723:45487人阅读评论(0)收藏举报Linuxicmp功能分析之
 

Linux icmp 学习笔记 之一 icmp协议相关的格式 分类: linux 网络 487人阅读 评论(0) 收藏 举报

Linux icmp功能分析 icmp协议相关的格式

 

ICMP协议是网络层中一个非常重要的协议,其全称为Internet Control Message Protocol(因特网控制报文协议),ICMP协议弥补了IP的缺限,它使用IP协议进行信息传递,向数据包中的源端节点提供发生在网络层的错误信息 反馈。

  在实现中,路由器会使用该协议来报告问题,而主机则会使用该机制来测试目的站是否可达。该报文的最终目的地不是一个应用程序或者目的设备上的用户,而是目的设备上的网际协议软件,一般icmp报文的接收是linux内核里的icmp接收模块来处理的,而icmp请求报文的发送即可以是内核里相关子系统也可以是应用层的程序发送(比如ping应用)。

 

1、  ICMP报文的格式

各种ICMP报文的前32bits都是三个长度固定的字段,为8bit的type字段、8bit的code字段、16bit的校验和字段(包括icmp数据字段的校验和),而对于不同类型的icmp报文,其余下字段的含义则是不同的。

 

a)       type类型

icmp类型目前有40个,下面几个是比较常用的,也是目前linux支持的类型。

回显应答(ECHO-REPLY

不可到达

源站抑制

重定向

回显请求(ECHO-REQUEST

11 数据报超时

12 参数失灵

13 时间戳请求

14 时间戳应答

15 信息请求(已不再使用)

16 信息应答(已不再使用)

17 地址掩码请求(已不再使用)

18 地址掩码应答(已不再使用)

对于 以上类型,比较重要的有:回显请求与应答(type 0、8)、不可到达(3)、源站抑制(4)、路由重定向(5)、时间戳请求与应答(13、14)

 

 

2、 主要的ICMP格式

a)      回显请求与应答

其中type值表示是一个回显请求或应答,code值为0,而identifier在linux的实现为进程pid(因为ping请求是应用程序,通过该值能够确认是机器上的哪一个应用程序执行的ping操作,能够对进行的接收数据进行匹配操作),而sequence则为一个计数器,主要是为每一个回显请求数据包设置序列值。Option是可选数据,其大小是可变的。

 

TYPE(8/0)

CODE(0)

Checksum

identifier

Sequence

Option

 

b)     目的站不可达

TYPE(3)

CODE(0-15)

Checksum

Not used (must set 0)

Option

 

由于目的站不可达的原因很多,所以需要用code来进行进一步细分。对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。

而code的定义如下:

#define ICMP_NET_UNREACH0 /* Network Unreachable */

#define ICMP_HOST_UNREACH1 /* Host Unreachable */

#define ICMP_PROT_UNREACH2 /* Protocol Unreachable */

#define ICMP_PORT_UNREACH3 /* Port Unreachable */

#define ICMP_FRAG_NEEDED4 /* Fragmentation Needed/DF set */

#define ICMP_SR_FAILED5 /* Source Route failed */

#define ICMP_NET_UNKNOWN6

#define ICMP_HOST_UNKNOWN7

#define ICMP_HOST_ISOLATED8

#define ICMP_NET_ANO9

#define ICMP_HOST_ANO10

#define ICMP_NET_UNR_TOS11

#define ICMP_HOST_UNR_TOS12

#define ICMP_PKT_FILTERED13 /* Packet filtered */

#define ICMP_PREC_VIOLATION14 /* Precedence violation */

#define ICMP_PREC_CUTOFF15 /* Precedence cut off */

#define NR_ICMP_UNREACH15 /* instead of hardcoding immediate value */

 

c)重定向

 

TYPE(5)

CODE(0-3)

Checksum

Route’s ip

Option

对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。

第二个32bits代表路由器的wan側地址。

Code类型如下:

#defineICMP_REDIR_NET        0     /* Redirect Net                     */

#defineICMP_REDIR_HOST             1     /* Redirect Host            */

#defineICMP_REDIR_NETTOS  2     /* Redirect Net for TOS        */

#defineICMP_REDIR_HOSTTOS       3     /* Redirect Host for TOS      */

重定向报文仅限于在直接连接到同一网络上的路由器与主机间交互。

 

d)数据包超时

因为每一个ip数据包都有一个ttl计数器,即跳数计数器,当数据包中的ttl的值为0时,就丢弃数据包,并发送一个数据包超时的icmp 报文。下面即是icmp 数据包超时报文的格式

 

TYPE(11)

CODE(0-1)

Checksum

Not used(must set 0)

Option

对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。

 

对于命令traceroute(windows 下为tracert),即是根据ttl来实现查找到目的站点所有跳点的ip地址的。即先发送3个ttl为1的数据包,根据接收到的icmp 数据包超时报文获取到第一个下一跳地址;然后再发送3个ttl为的数据包,根据接收到的数据包超时报文获取到第二个下一跳地址;依此类推直到找到所有的跳点地址或者已经到了ttl的max值还没有到目的站点则程序返回。

 

基本上这4个icmp报文是最重要的了。

3、 linux中icmp相关的数据结构

 

#defineICMP_ECHOREPLY              0     /* Echo Reply               */

#defineICMP_DEST_UNREACH       3     /* Destination Unreachable    */

#defineICMP_SOURCE_QUENCH    4     /* Source Quench          */

#defineICMP_REDIRECT          5     /* Redirect (change route)     */

#defineICMP_ECHO           8     /* Echo Request                   */

#defineICMP_TIME_EXCEEDED     11    /* Time Exceeded          */

#defineICMP_PARAMETERPROB     12    /* Parameter Problem           */

#defineICMP_TIMESTAMP        13    /* Timestamp Request           */

#defineICMP_TIMESTAMPREPLY    14    /* Timestamp Reply              */

#defineICMP_INFO_REQUEST  15    /* Information Request         */

#defineICMP_INFO_REPLY              16    /* Information Reply            */

#defineICMP_ADDRESS           17    /* Address Mask Request              */

#defineICMP_ADDRESSREPLY 18    /* Address Mask Reply          */

#defineNR_ICMP_TYPES          18

 

 

/*Codes for UNREACH. */

#defineICMP_NET_UNREACH  0     /* Network Unreachable        */

#defineICMP_HOST_UNREACH       1     /* Host Unreachable             */

#defineICMP_PROT_UNREACH       2     /* Protocol Unreachable        */

#defineICMP_PORT_UNREACH       3     /* Port Unreachable              */

#defineICMP_FRAG_NEEDED  4     /* Fragmentation Needed/DF set   */

#defineICMP_SR_FAILED         5     /* Source Route failed          */

#defineICMP_NET_UNKNOWN 6

#defineICMP_HOST_UNKNOWN     7

#defineICMP_HOST_ISOLATED       8

#defineICMP_NET_ANO           9

#defineICMP_HOST_ANO         10

#defineICMP_NET_UNR_TOS   11

#defineICMP_HOST_UNR_TOS 12

#defineICMP_PKT_FILTERED   13    /* Packet filtered */

#defineICMP_PREC_VIOLATION     14    /* Precedence violation */

#defineICMP_PREC_CUTOFF    15    /* Precedence cut off */

#defineNR_ICMP_UNREACH           15    /* instead of hardcoding immediate value */

 

/*Codes for REDIRECT. */

#defineICMP_REDIR_NET        0     /* Redirect Net                     */

#defineICMP_REDIR_HOST             1     /* Redirect Host            */

#defineICMP_REDIR_NETTOS  2     /* Redirect Net for TOS        */

#defineICMP_REDIR_HOSTTOS       3     /* Redirect Host for TOS      */

 

/*Codes for TIME_EXCEEDED. */

#defineICMP_EXC_TTL             0     /* TTL count exceeded          */

#defineICMP_EXC_FRAGTIME 1     /* Fragment Reass time exceeded  */

 

Icmp头部定义:

structicmphdr {

  __u8           type;

  __u8           code;

  __sum16     checksum;

  union {

       struct {

              __be16    id;

              __be16    sequence;

       } echo;

       __be32    gateway;

       struct {

              __be16    __unused;

              __be16    mtu;

       } frag;

  } un;

};

在该数据结构中,前32bits的定义是一样的,而后面32bits的定义,因回显请求与应答、重定向等报文定义不同而有不同的含义。

 

发送icmp报文相关的数据结构。

structicmp_bxm {

       struct sk_buff *skb;//接收到的icmp报文

       int offset;//选项数据在icmp数据中的偏移量

       int data_len;//icmp数据报文长度

 

       struct {

              struct icmphdr icmph;/icmp头部/

              __be32           times[3];

       } data;

       int head_len;//icmp头部长度

       struct ip_options replyopts;//存储的接收icmp报文的选项数据,待发送时使用

       unsigned char  optbuf[40];

};


 

Linux icmp 学习笔记 之二 icmp数据处理流程分类: linux 网络 925人阅读 评论(0) 收藏 举报


 

在分析icmp数据包处理流程之前,我有如下疑问:

1、为什么要为每一个cpu创建一个仅用于发送icmp报文的socket呢,不使用socket不也是可以把icmp报文发送出去吗?

2、ping的工作原理是什么呢?

3、Traceroute的工作原理是什么呢?

 

一、imcp协议的初始化

1)ICMP接收处理函数的初始化

我们知道icmp协议是附属于ip层的3层协议,且是将icmp数据存放于ip数据包的数据部分的3层协议。而tcp、udp也是将tcp、udp数据存放于ip数据包的数据部分的4层协议。

虽然icmp与tcp等协议不属于同一个网络层,但是都是在3层ip协议处理完以后,才会交给icmp、tcp的处理函数去处理。因此在linux中,都是调用inet_add_protocol将其接收处理函数相关的数据结构添加到数组inet_protos中去的(关于三、四层接收数据处理函数的注册相关的知识请参看http://blog.csdn.net/lickylin/article/details/22900401)。

       Icmp的接收处理函数相关的结构体定义如下:

static const struct net_protocol icmp_protocol = {

    .handler =       icmp_rcv,

    .no_policy =   1,

    .netns_ok =     1,

};

在inet_init初始化时,即会调用inet_add_protocol将tcp、udp、icmp、igmp等协议相关的接收处理结构体注册,并保存在数组inet_protos中。

 

当接收的数据包的协议为icmp时,即会调用icmp_rcv进行后续处理。

 

 

2)  icmp协议模块的初始化

主要是调用函数register_pernet_subsys(关于该函数的工作流程,请参看http://blog.csdn.net/lickylin/article/details/18013879),将icmp协议模块注册到网络命令空间中,并调用ops->init进行协议初始化相关的代码。

对于icmp,其pernet_operations的定义如下:

static structpernet_operations __net_initdata icmp_sk_ops = {

       .init = icmp_sk_init,

       .exit = icmp_sk_exit,

};

在调用register_pernet_subsys将icmp协议模块注册到网络命名空间后,即会调用icmp_sk_init进行icmp协议初始化相关的功能,我们分析下icmp_sk_init。

 

 

该函数主要实现以下功能:

/*

1、  为每一个cpu创建一个用于发生icmp数据包的socket

2、  设置一些限制条件,包括速率限制、接收数据包的条件等

*/

static int __net_init icmp_sk_init(struct net *net)

{

    int i, err;

 

/*为icmp_sk申请空间,该icmp_sk数组中存放了所有cpu相关的socket指针*/

    net->ipv4.icmp_sk =

           kzalloc(nr_cpu_ids *sizeof(struct sock *), GFP_KERNEL);

    if (net->ipv4.icmp_sk ==NULL)

           return -ENOMEM;

 

    /*为每一个cpu创建一个RAW套接字*/

    for_each_possible_cpu(i) {

           struct sock *sk;

           /*

创建一个 RAW 类型的套接字,并调用(*sk)->sk_prot->unhash,将该socket从hash链表raw_v4_hashinfo.ht[RAW_HTABLE_SIZE]中删除与该socket的关联

*/

           err =inet_ctl_sock_create(&sk, PF_INET,

                                   SOCK_RAW, IPPROTO_ICMP, net);

           if (err <0)

                  goto fail;

 

           net->ipv4.icmp_sk[i]= sk;

 

           /* Enough space for2 64K ICMP packets, including

            * sk_buff struct overhead.

            */

           sk->sk_sndbuf =

                  (2 * ((64 *1024) + sizeof(struct sk_buff)));

 

           /*

            * Speedup sock_wfree()

            */

           sock_set_flag(sk,SOCK_USE_WRITE_QUEUE);

           inet_sk(sk)->pmtudisc= IP_PMTUDISC_DONT;

    }

 

    net->ipv4.sysctl_icmp_echo_ignore_all= 0;

    /*忽略广播的echo请求 */

    net->ipv4.sysctl_icmp_echo_ignore_broadcasts= 1;

 

    /* 忽略广播的icmp 错误回复信息*/

    net->ipv4.sysctl_icmp_ignore_bogus_error_respOnses= 1;

 

    net->ipv4.sysctl_icmp_ratelimit= 1 * HZ; //速率限制值

/*进行速率限制的icmp数据包类型,主要有dest unreachable 、source quench time exceeded 、parameter problem*/

    net->ipv4.sysctl_icmp_ratemask= 0x1818;

    net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr= 0;

 

    return 0;

 

fail:

    for_each_possible_cpu(i)

           inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);

    kfree(net->ipv4.icmp_sk);

    return err;

}

 

疑问:当新创建的socket时,为什么要将其从hash链表raw_v4_hashinfo.ht[RAW_HTABLE_SIZE]中删除呢?

 

因为我们只使用这个socket进行发送数据包,而不需要使用该socket接收数据包。所以此处将其从hash链表raw_v4_hashinfo.ht[RAW_HTABLE_SIZE]中删除。

为什么不使用该socket直接接收icmp报文呢,我的理解是如果使用该socket接收报文,就需要在kernel创建一个内核线程,用于侦听是否有数据到达该socket,然后再进行处理。

而直接使用内核四层协议接收处理函数的注册流程,可以很方便的就能对接收的icmp报文进行处理,而且使用的内核资源比较少,所以对于kernel创建的socket,其接收操作基本上是使用内核四层协议接收处理函数的注册流程实现的。而对于应用层创建的icmp相关的socket则不会执行上述操作。

 

 

 

二、ICMP协议的接收处理函数

Icmp接收处理函数为icmp_rcv,下面分析这个函数。

 

主要功能:

1、  对数据包进行合理性检查

2、  根据icmp的类型,

int icmp_rcv(struct sk_buff *skb)

{

       structicmphdr *icmph;

       structrtable *rt = skb_rtable(skb);

       structnet *net = dev_net(rt->u.dst.dev);

 

       /*

       基于策略的高扩展性的网络安全架构,对于这个内核子架构不清楚

     此处分析不了,跳过。

       */

       if(!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {

              structsec_path *sp = skb_sec_path(skb);

              intnh;

 

              if(!(sp && sp->xvec[sp->len - 1]->props.flags &

                             XFRM_STATE_ICMP))

                     gotodrop;

 

              if(!pskb_may_pull(skb, sizeof(*icmph) + sizeof(struct iphdr)))

                     gotodrop;

 

              nh= skb_network_offset(skb);

              skb_set_network_header(skb,sizeof(*icmph));

 

              if(!xfrm4_policy_check_reverse(NULL, XFRM_POLICY_IN, skb))

                     gotodrop;

 

              skb_set_network_header(skb,nh);

       }

 

       ICMP_INC_STATS_BH(net,ICMP_MIB_INMSGS);

       /*验证校验和信息*/

       switch(skb->ip_summed) {

       caseCHECKSUM_COMPLETE:

              if(!csum_fold(skb->csum))

                     break;

              /*fall through */

       caseCHECKSUM_NONE:

              skb->csum= 0;

              if(__skb_checksum_complete(skb))

                     gotoerror;

       }

 

       if(!pskb_pull(skb, sizeof(*icmph)))

              gotoerror;

       /*获取icmp头部*/

       icmph= icmp_hdr(skb);

 

       ICMPMSGIN_INC_STATS_BH(net,icmph->type);

       /*

       对于不支持的icmp报文,直接丢掉

        */

       if(icmph->type > NR_ICMP_TYPES)

              gotoerror;

 

 

       /*

       判断是否丢弃掉多播类型的icmp数据包

       1、只处理echo、timestamp、address_mask_request、address_mask_reply类型的多播icmp数据包

        */

 

       if(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {

              /*

               *    RFC1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be

               *      silently ignored (we let user decide with asysctl).

               *    RFC1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently

               *      discarded if to broadcast/multicast.

               */

              if((icmph->type == ICMP_ECHO ||

                   icmph->type == ICMP_TIMESTAMP)&&

                 net->ipv4.sysctl_icmp_echo_ignore_broadcasts) {

                     gotoerror;

              }

              if(icmph->type != ICMP_ECHO &&

                  icmph->type != ICMP_TIMESTAMP &&

                  icmph->type != ICMP_ADDRESS &&

                  icmph->type != ICMP_ADDRESSREPLY) {

                     gotoerror;

              }

       }

       /*根据icmp数据包类型,调用相应的处理函数*/

       icmp_pointers[icmph->type].handler(skb);

 

drop:

       kfree_skb(skb);

       return0;

error:

       ICMP_INC_STATS_BH(net,ICMP_MIB_INERRORS);

       gotodrop;

}

 

 

 

对于icmp_pointers的定义如下:

/*

 *    This table is the definition of how wehandle ICMP.

 */

static const struct icmp_controlicmp_pointers[NR_ICMP_TYPES + 1] = {

       [ICMP_ECHOREPLY]= {

              .handler= icmp_discard,

       },

       [1]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [2]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [ICMP_DEST_UNREACH]= {

              .handler= icmp_unreach,

              .error= 1,

       },

       [ICMP_SOURCE_QUENCH]= {

              .handler= icmp_unreach,

              .error= 1,

       },

       [ICMP_REDIRECT]= {

              .handler= icmp_redirect,

              .error= 1,

       },

       [6]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [7]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [ICMP_ECHO]= {

              .handler= icmp_echo,

       },

       [9]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [10]= {

              .handler= icmp_discard,

              .error= 1,

       },

       [ICMP_TIME_EXCEEDED]= {

              .handler= icmp_unreach,

              .error= 1,

       },

       [ICMP_PARAMETERPROB]= {

              .handler= icmp_unreach,

              .error= 1,

       },

       [ICMP_TIMESTAMP]= {

              .handler= icmp_timestamp,

       },

       [ICMP_TIMESTAMPREPLY]= {

              .handler= icmp_discard,

       },

       [ICMP_INFO_REQUEST]= {

              .handler= icmp_discard,

       },

       [ICMP_INFO_REPLY]= {

              .handler= icmp_discard,

       },

       [ICMP_ADDRESS]= {

              .handler= icmp_address,

       },

       [ICMP_ADDRESSREPLY]= {

              .handler= icmp_address_reply,

       },

};

 

目前内核处理的icmp报文有icmp_unreach、icmp_address、icmp_address_reply、icmp_timestamp、icmp_echo、icmp_redirect。

 

 

icmp_echo

 

/*

该函数主要是将icmp的type设置为ICMP_ECHOREPLY,并调用icmp_reply将该数据包发送出去

*/

 

static void icmp_echo(struct sk_buff *skb)

{

       structnet *net;

 

       net= dev_net(skb_dst(skb)->dev);

       if(!net->ipv4.sysctl_icmp_echo_ignore_all) {

              structicmp_bxm icmp_param;

 

              icmp_param.data.icmph    =*icmp_hdr(skb);

              icmp_param.data.icmph.type= ICMP_ECHOREPLY;

              icmp_param.skb              = skb;

              icmp_param.offset     = 0;

              icmp_param.data_len        =skb->len;

              icmp_param.head_len       =sizeof(struct icmphdr);

              icmp_reply(&icmp_param,skb);

       }

}

 

Timestamp

/*

设置时间戳的值,并将icmp的type设置为ICMP_TIMESTAMPREPLY,并通过icmp_reply发送出去

*/

static void icmp_timestamp(struct sk_buff*skb)

{

       structtimespec tv;

       structicmp_bxm icmp_param;

       /*

        *    Tooshort.

        */

       if(skb->len <4)

              gotoout_err;

 

       /*

        *    Fillin the current time as ms since midnight UT:

        */

       getnstimeofday(&tv);

       icmp_param.data.times[1]= htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +

                                    tv.tv_nsec / NSEC_PER_MSEC);

       icmp_param.data.times[2]= icmp_param.data.times[1];

       if(skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))

              BUG();

       icmp_param.data.icmph    =*icmp_hdr(skb);

       icmp_param.data.icmph.type= ICMP_TIMESTAMPREPLY;

       icmp_param.data.icmph.code= 0;

       icmp_param.skb              = skb;

       icmp_param.offset     = 0;

       icmp_param.data_len       =0;

       icmp_param.head_len       =sizeof(struct icmphdr) + 12;

       icmp_reply(&icmp_param,skb);

out:

       return;

out_err:

       ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev),ICMP_MIB_INERRORS);

       gotoout;

}

 

 

Unreach 数据处理

 

功能:根据icmp中有效载荷数据的值,调用传输层的错误处理函数进行处理

static void icmp_unreach(struct sk_buff*skb)

{

       structiphdr *iph;

       structicmphdr *icmph;

       inthash, protocol;

       conststruct net_protocol *ipprot;

       u32info = 0;

       structnet *net;

 

       net= dev_net(skb_dst(skb)->dev);

 

       /*

        *    Incompleteheader ?

        *   Onlychecks for the IP header, there should be an

        *    additionalcheck for longer headers in upper levels.

        */

 

       if(!pskb_may_pull(skb, sizeof(struct iphdr)))

              gotoout_err;

 

       /*获取icmp首部*/

       icmph= icmp_hdr(skb);

       iph   = (struct iphdr *)skb->data;

 

       /*判断ip首部是否完整*/

       if(iph->ihl <5) /* Mangled header, drop. */

              gotoout_err;

 

       /*仅处理type类型为3或者12的数据包

       1、当类型为3时,仅处理code为frag needed的报文

           a)当系统不支持pmtu时,丢弃该数据包

           b)当系统支持pmtu时,调用ip_rt_frag_needed修改pmtu的值

       2、当type类型为12时,则通过icmph->un.gateway获取出错偏移值(相对于数据包)

       */

       if(icmph->type == ICMP_DEST_UNREACH) {

              switch(icmph->code & 15) {

              caseICMP_NET_UNREACH:

              caseICMP_HOST_UNREACH:

              caseICMP_PROT_UNREACH:

              caseICMP_PORT_UNREACH:

                     break;

              caseICMP_FRAG_NEEDED:

                     if(ipv4_config.no_pmtu_disc) {

                            LIMIT_NETDEBUG(KERN_INFO"ICMP: %pI4: fragmentation needed and DF set.\n",

                                          &iph->daddr);

                     }else {

                            info= ip_rt_frag_needed(net, iph,

                                                  ntohs(icmph->un.frag.mtu),

                                                  skb->dev);

                            if(!info)

                                   gotoout;

                     }

                     break;

              caseICMP_SR_FAILED:

                     LIMIT_NETDEBUG(KERN_INFO"ICMP: %pI4: Source Route Failed.\n",

                                   &iph->daddr);

                     break;

              default:

                     break;

              }

              if(icmph->code > NR_ICMP_UNREACH)

                     gotoout;

       }else if (icmph->typ

推荐阅读
  • Linuxchmod目录权限命令图文详解在Linux文件系统模型中,每个文件都有一组9个权限位用来控制谁能够读写和执行该文件的内容。对于目录来说,执行位的作用是控制能否进入或者通过 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文主要讨论了在xps15上安装双系统win10和MacOS后,win10无法正常更新的问题。分析了可能的引导问题,并提供了解决方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
author-avatar
低調浮華
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有