热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

全面剖析《自己动手写操作系统》第五章makefile文件

转载请标注:全面剖析《自己动手写操作系统》第五章---makefile文件http:blog.csdn.netzgh1988articledetails73383

转载请标注: 

全面剖析《自己动手写操作系统》第五章---makefile文件  

http://blog.csdn.net/zgh1988/article/details/7338380

1、make概述

2、编译和链接

3、makefile规则

4、自己动手写makefile文件

5、后记


一、make概述


        作为程序员,我们都有使用过Visualstdio 2005、VC6.0、eclipse等经典开发工具,使用它们,我们可以方便地建立和管理自己的工程,往往直接点击两个按钮,就完成了编译,链接,运行等功能。但是我们有没有过这样的疑问?它是怎样做到的,它是怎样将不在一起的文件组合到一起的,我们自己能不能管理自己的工程呢。是的,在Linux环境下使用GNU的make工具就可以构建和管理自己的工程,而且还可以自己操作它们的编译、链接等。

        在了解make工具之前,我们需要知道makefile文件,该文件就是用来描述整个工程的编译、链接等规则,其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何最后产生我们想要得到的可执行文件。我们的任务就是要掌握如何书写makefile文件。makefile文件有自己的书写格式、关键字、函数,而且可以使用系统shell所提供的任何命令(例如:nasm gcc等指令)。

        make是一个命令工具,它解释makefile文件中的指令。在书写好makefile文件之后,我们只需要在shell提示符下输入make命令,整个工程就会按照makefile文件中的内容完全自动编译,极大的提高了效率。

二、编译和链接

        传统意义上,在生成系统可执行文件之前,需要进行两步走战略:编译和链接。

        编译(compile):指用编译器(compiler)将源代码(sourcecode)生成二进制目标文件(object file),在Windows下也就是 .obj 文件,Linux下是 .o 文件。编译时,编译器需要检查高级语言的语法,函数与变量的声明是否正确。只有所有语法正确,函数与变量声明正确,编译器就可以编译出二进制目标文件。为了和最终生成的可执行目标文件区别,我们暂且称编译后的目标文件为.o文件。

        链接(link):找到所要用到函数所在的目标文件(.o文件),并把它们链接在一起合成为可执行文件(executable file),在Linux环境下,可执行文件的格式为“ELF”格式。链接时,要确保编译器能找到所有被用到了的函数所在的目标文件。链接过程中使用GNU的“ld”工具。

三、makefile规则

一个简单的makefile规则:

TARGET :PREREQUISITES

        COMMAND

从这个形式上来看,我们可以得到两层含义:

(1) 要想得到TARGET,需要执行命令COMMAND。

(2) TARGET依赖于PREREQUISITES,当PREREQUISITES中至少有一个文件比TARGET文件新时,COMMAND才被执行。

        TARGET :规则的目标。通常是最终可以在系统上运行的目标文件 或 实现这个目标文件所需要的中间过程文件。例如.o文件 或者 最后的可执行文件。另外,目标也可以是一个make执行的动作名称,如目标“clean”,不过我们称这样的目标为“伪目标”。

        PREREQUISITES : 规则的依赖。生成规则目标所需要的文件列表,通常一个目标文件依赖于一个或者多个文件。

        COMMAND : 规则的命令行。是规则所要执行的动作。

        (语法1)一个规则可以有多个命令行,每一条命令行占一行。注意:每一个命令行必须以【TAB】字符开始,【TAB】字符告诉make此行是一个命令行。

四、自己动手写makefile

1、一个简单的例子


目标:生成boot.bin和loader.bin文件

条件:boot.asm 包含 load.inc fat12hdr.inc

            loader.asm 包含 load.incfat12hdr.inc pm.inc

下面我们开始写makefile文件:

(1) 首先我们要写出生成boot.bin 的规则:

boot.bin : boot.asm load.inc fat12hdr.inc

         nasm–o boot.bin boot.asm

另外我们写出生成loader.bin的规则:

loader.bin : loader.asm load.incfat12hdr.inc pm.inc

         nasm–o loader.bin loader.asm

我们将这两条规则保存到makefile文件中,将makefile文件放在boot文件下。

此时,如果我们只输入命令行make,发现它只是执行了第一条规则,也就是只生成了boot.bin目标文件。(语法2)因为在默认情况下,make执行的是makefile中的第一个规则。如果想执行第二条规则,我们必须执行make loader.bin,才能够达到目的。

(2) 问题又来了,我们如何通过一条命令把两个规则都执行了呢?我在文件开始处,添加了这样的一条规则,作为该makefile的第一条规则。

everything : boot.bin loader.bin        

这个规则虽然命令行为空,也就是不做任何工作,但是makefile中有这样一条规则,(语法3)make在执行一条规则所定义的命令之前,首先需要处理的是目标文件的所有的依赖文件,在此规则中,也就是boot.bin 和 loader.bin。如果依赖文件不存在,则make会按照依赖文件列表从左到右的顺序依次寻找创建这些依赖文件的规则。

所以在本例中,在执行everything: boot.bin loader.bin这条规则之前,make发现其依赖文件boot.bin 和loader.bin文件不存在,就会去寻找创建这些依赖条件的规则,即规则2,和规则3,分别执行规则2,3,完成boot.bin loader.bin的创建。

(3) 此时我们在输入命令make,会发现一个错误:make:`everything' is up to date。这是为什么呢?难道我们写的规则出现问题了吗?

        我们写的makefile文件是正确的,下面我来告诉你makefile的另一条规则(语法4)在执行一条规则中,如果目标文件不存在,则执行该规则以创建目标文件;如果目标文件存在,其依赖文件中有一个或者多个文件比它“更新”—也就是说依赖文件中有一个或者多个文件在目标文件生成之后,进行了修改,则根据规则重新创建目标文件;如果目标文件存在,它比它的任何一个依赖文件都要“更新”—也就是说在生成目标文件之后,所有的依赖文件都没有发生修改,则什么都不做。

        所以此时执行make命令会发生错误。因为之前我们已经生成了boot.bin 和 loader.bin文件,而且其依赖文件列表没有更新。

        此时怎么办呢?让我们在写一条规则放在最后一行:

clean :

         rm–f boot.bin loader.bin

它不存在依赖条件,它是一条伪规则,命令行的作用是删除文件boot.bin loader.bin。我们通常使用rm指令,来删除一些中间生成文件(例如.o文件)。

(4) 最终的makefile文件如下:

everything : boot.bin loader.bin     

boot.bin : boot.asm load.inc fat12hdr.inc

         nasm-o boot.bin boot.asm

loader.bin : loader.asm load.incfat12hdr.inc pm.inc

         nasm-o loader.bin loader.asm

clean:      

         rm-f boot.bin loader.bin

 

现在我们就可以先执行一个make clean,将目标文件boot.bin loader.bin删除,然后再执行make命令。执行结果如下:


这样我们就完成了我们第一个最简单的例子。

下面让我们来回忆上面所提到的4条规则:

(语法1)一个规则可以有多个命令行,每一条命令行占一行。注意:每一个命令行必须以[TAB]字符开始,【TAB】字符告诉make此行是一个命令行。

(语法2)因为在默认情况下,make执行的是makefile中的第一个规则。

(语法3)make在执行一条规则所定义的命令之前,首先需要处理的是目标文件的所有的依赖文件,如果依赖文件不存在,则make会按照依赖文件列表从左到右的顺序依次寻找创建这些依赖文件的规则。

(语法4)在执行一条规则中,如果目标文件不存在,则执行该规则以创建目标文件;如果目标文件存在,其依赖文件中有一个或者多个文件比它“更新”—也就是说依赖文件中有一个或者多个文件在目标文件生成之后,进行了修改,则根据规则重新创建目标文件;如果目标文件存在,它比它的任何一个依赖文件都要“更新”—也就是说在生成目标文件之后,所有的依赖文件都没有发生修改,则什么都不做。

2、又是一个简单的问题



        此时,为了让整个工程规范,我将头文件load.inc fat12hdr.inc pm.inc放在包含在include下的文件夹里面。此时的makefile文件还是在boot文件夹目录下,此时的makefile该怎么写呢?如果我们不加修改的话,运行make指令肯定会出问题。原因是无法找到依赖文件列表中的load.inc fat12hdr.inc pm.inc文件,因为它们的路径不在/boot下,而是搬到了boot/include下。所以修改makefile文件如下:

everything : boot.bin loader.bin     

boot.bin : boot.asm include/load.incinclude/fat12hdr.inc

         nasm-I include -o boot.bin boot.asm

loader.bin : loader.asm include/load.incinclude/fat12hdr.inc include/pm.inc

         nasm-I include -o loader.bin loader.asm

clean:      

         rm-f boot.bin loader.bin

 

我们相当于添加了一个路径来帮助make自己寻找这些头文件。在nasm指令中,-I 指的就是路径。

下面是运行结果:

3、为makefile添加变量

        这时候,你有没有想过,如果我的工程不断的扩大,到时候我这样一点点的写是不是很麻烦,还会出好多问题。

        其实我还有一点没有告诉你呢,在makefile中,是可以添加变量的。所以我们就要将一些内容赋值给变量,在以后的道路上,我们就可以修改变量了。

        在此问题上,我就要添加变量来简化makefile文件,使其更加清晰明了。

# Makefile for boot

# Programs, flags,etc.

ASM              = nasm

ASMFLAGS = -I include

# This Program

TARGET    =  boot.bin loader.bin

# All Phony Targets

.PHONY : everything clean all

# Default starting position

everything :      $(TARGET)

clean :

         rm -f $(TARGET)

all :   clean everything

 

boot.bin : boot.asminclude/load.inc include/fat12hdr.inc

         $(ASM)  $(ASMFLAGS) -o $&#64; $<

loader.bin :loader.asm include/load.inc include/fat12hdr.inc include/pm.inc

         $(ASM)  $(ASMFLAGS) -o $&#64; $<

 

        首先&#xff0c;我们看到的是两个命令行变量&#xff0c;ASM &#61; nasm  ASMFLAGS &#61; -Iinclude

        在今后我们使用到nasm 和–I include 时&#xff0c;我们就只需要用$(ASM)&#xff0c; $(ASMFLAGS)来代替&#xff0c;$这个符号的含义&#xff0c;就是取值操作。

        其次是TARGET &#61; boot.bin loader.bin&#xff0c;我们定义了一个目标变量&#xff0c;它的值保护boot.bin和loader.bin。所以在

everything &#xff1a;$(TARGET)  相当于everything : boot.bin loader.bin。

        然后你注意到了我们将everything clean all定义为了.PHONY&#xff0c;我们知道everything clean all只是动作&#xff0c;它是伪规则&#xff0c;所以我们用.PHONY来定义它们。

        最后是两个规则&#xff0c;一个是生成boot.bin&#xff0c;一个是loader.bin。

$(ASM) $(ASMFLAGS) –o $&#64; $<相当于&#xff1a;

nasm -I include -o loader.bin loader.asm

S&#64; &#61; loader.bin  $<&#61; loader.asm

        这时候我们发现&#xff0c;我们的第二个规则有点长&#xff0c;所以我们需要将其变短一些。&#xff08;语法5&#xff09;这时候我们需要使用反斜线&#xff08;\&#xff09;将一个较长的行分成多行&#xff0c;这样我们的makefile书写清晰、容易阅读理解。但需要注意&#xff1a;反斜线之后不能有空格&#xff08;这也是大家最容易犯的错误&#xff0c;错误比较隐蔽&#xff09;

loader.bin : loader.asm include/load.incinclude/fat12hdr.inc \

                    include/pm.inc

         $(ASM)$(ASMFLAGS) -o $&#64; $<

4、一个复杂的问题



这是本章中最后生成的操作系统的工程目录表&#xff0c;通过它我们来熟悉书写makefile的步骤&#xff1a;
(1) 我们应该找到目标文件和依赖文件之间的关系

boot/boot.asm : boot/boot.asm boot/include/load.inc boot/include/fat12hdr.inc
boot/loader.asm : boot/loader.asm boot/include/load.inc boot/include/fat12hdr.inc \
boot/include/pm.inc
kernel/kernel.o : kernel/kernel.asm
kernel/start.o : kernel/start.c include/type.h include/const.h include/protect.h \include/proto.h include/string.h include/global.h
kernel/i8259.o : kernel/i8259.c include/type.h include/const.h include/protect.h \include/proto.h
kernel/global.o : kernel/global.c include/type.h include/const.h include/protect.h \include/proto.h include/global.h
kernel/protect.o : kernel/protect.c include/type.h include/const.h include/protect.h \include/global.h
lib/klib.o : lib/klib.asm
lib/string.o : lib/string.asm
lib/klibc.o : lib/klib.c include/type.h include/const.h include/protect.h include/string.h \include/proto.h include/global.h
kernel.bin : kernel/kernel.o kernel/start.o kernel/i8259.o kernel/global.o kernel/protect.o \
lib/klib.o lib/string.o lib/klibc.o

(2) 根据上面的目标文件&#xff0c;我们需要定义目标变量&#xff0c;此时不要求完整&#xff0c;随着思考一步步的去完善。

TINIXBOOT       &#61; boot/boot.bin boot/loader.bin

TINIXKERNEL  &#61; kernel.bin

OBJS                 &#61; kernel/kernel.o kernel/start.okernel/i8259.o kernel/global.o kernel/protect.o lib/klib.o lib/string.olib/klibc.o

DASMOUTPUT&#61; kernel.bin.asm

(3) 我们可以需要取定义一些命令变量&#xff0c;此时不要求完整&#xff0c;随着思考一步步的去完善。

ASM          &#61;nasm

DASM       &#61;ndisasm

CC             &#61;gcc

LD              &#61;ld

ASMBFLAGS     &#61;-I boot/include

ASMKFLAGS     &#61;-I include -f elf

ASMKLFLAGS   &#61;-f elf

CFLAGS              &#61;-I include -c -fno-builtin

LDFLAGS           &#61;-s -Ttext $(ENTRYPOINT)

DASMFLAGS     &#61;-u -o $(ENTRYPOINT) -e $(ENTRYOFFSET)

(4) 然后我们开始尝试组织这些变量&#xff0c;生成各种规则。

boot/boot.bin : boot/boot.asm boot/include/load.inc boot/include/fat12hdr.inc$(ASM) $(ASMBFLAGS) -o $&#64; $

(5) 最后需要完成一些不同的伪规则&#xff0c;也就是行为&#xff0c;将其中的某些行为进行组合。

# All Phony Targets
.PHONY : everything final image cleanrealclean disasm all buildimg
# Default starting position
everything : $(TINIXBOOT) $(TINIXKERNEL)
all : realclean everythingfinal : all cleanimage : final buildimgclean :rm -f $(OBJS)
realclean:rm -f $(OBJS) $(TINIXBOOT) $(TINIXKERNEL)
disasm :$(DASM) $(DASMFLAGS) $(TINIXKERNEL) > $(DASMOUTPUT)# Write "boot.bin" &"loader.bin" into floppy image "TINIX.IMG"
# We assume that "TINIX.IMG"exists in current folder
buildimg:mount Tinix.vfd /mnt/floppy -o loopcp -f boot/loader.bin /mnt/floppycp -f kernel.bin /mnt/floppyumount /mnt/floppy

make&#43;不同的伪规则形成不同的结果&#xff1a;

make everything:
nasm -I boot/include -o boot/boot.binboot/boot.asm
nasm -I boot/include -o boot/loader.binboot/loader.asm
nasm -I include -f elf -o kernel/kernel.o kernel/kernel.asm
gcc -I include -c -fno-builtin -okernel/start.o kernel/start.c
nasm -f elf -o lib/klib.o lib/klib.asm
nasm -f elf -o lib/string.o lib/string.asm
ld -s -Ttext 0x30400 -o kernel.binkernel/kernel.o kernel/start.o lib/klib.o lib/string.omake clean:
rm -f kernel/kernel.o kernel/start.o lib/klib.o lib/string.omake realclean:
rm -f kernel/kernel.o kernel/start.o lib/klib.o lib/string.o boot/boot.bin boot/loader.bin kernel.binmake buildimg:
mount Tinix.vfd /mnt/floppy -o loop
cp -f boot/loader.bin /mnt/floppy
cp -f kernel.bin /mnt/floppy
umount /mnt/floppymake all:
make realclean
make everythingmake final:
make all (make realclean make everything)
make cleanmake image:
make final (make all(make realclean makeeverything))
make buildimg

(6) 最后的结果如下&#xff1a;

# Makefile for TINIX# Entry Point of Tinix
# It must be as same as &#39;KernelEntryPointPhyAddr&#39; in load.inc!!!
ENTRYPOINT &#61; 0x30400# Offset of entry point in kernel file
# It depends on ENTRYPOINT
ENTRYOFFSET &#61; 0x400# Programs, flags, etc.
ASM &#61; nasm
DASM &#61; ndisasm
CC &#61; gcc
LD &#61; ld
ASMBFLAGS &#61; -I boot/include
ASMKFLAGS &#61; -I include -f elf
ASMKLFLAGS &#61; -f elf
CFLAGS &#61; -I include -c -fno-builtin
LDFLAGS &#61; -s -Ttext $(ENTRYPOINT)
DASMFLAGS &#61; -u -o $(ENTRYPOINT) -e $(ENTRYOFFSET)# This Program
TINIXBOOT &#61; boot/boot.bin boot/loader.bin
TINIXKERNEL &#61; kernel.bin
OBJS &#61; kernel/kernel.o kernel/start.o kernel/i8259.o kernel/global.o kernel/protect.o lib/klib.o lib/string.o lib/klibc.o
DASMOUTPUT &#61; kernel.bin.asm# All Phony Targets
.PHONY : everything final image clean realclean disasm all buildimg# Default starting position
everything : $(TINIXBOOT) $(TINIXKERNEL)all : realclean everythingfinal : all cleanimage : final buildimgclean : rm -f $(OBJS)realclean:rm -f $(OBJS) $(TINIXBOOT) $(TINIXKERNEL)disasm :$(DASM) $(DASMFLAGS) $(TINIXKERNEL) > $(DASMOUTPUT)# Write "boot.bin" & "loader.bin" into floppy image "TINIX.IMG"
# We assume that "TINIX.IMG" exists in current folder
buildimg:mount Tinix.vfd /mnt/floppy -o loopcp -f boot/loader.bin /mnt/floppycp -f kernel.bin /mnt/floppyumount /mnt/floppyboot/boot.bin : boot/boot.asm boot/include/load.inc boot/include/fat12hdr.inc$(ASM) $(ASMBFLAGS) -o $&#64; $
五、后记

本着够用原则&#xff0c;只学习了这么一点关于makefile的知识&#xff0c;希望在以后的时间里&#xff0c;能够对makefile进行深入研究。


全面剖析《自己动手写操作系统》第五章---加载内核kernel.bin http://blog.csdn.net/zgh1988/article/details/7329941

全面剖析《自己动手写操作系统》第五章---Red Hat 9.0 的安装过程  http://blog.csdn.net/zgh1988/article/details/7315676

全面剖析《自己动手写操作系统》第四章---FAT12文件系统 http://blog.csdn.net/zgh1988/article/details/7284834

全面剖析《自己动手写操作系统》第四章---加载Loader.bin http://blog.csdn.net/zgh1988/article/details/7291909

全面剖析《自己动手写操作系统》第三章---进入保护模式   http://blog.csdn.net/zgh1988/article/details/7098981

全面剖析《自己动手写操作系统》第三章---“实模式--保护模式--实模式” http://blog.csdn.net/zgh1988/article/details/7255804

全面剖析《自己动手写操作系统》第三章---堆栈段的工作方式 http://blog.csdn.net/zgh1988/article/details/7256254

全面剖析《自己动手写操作系统》第三章---特权级以及不同特权级代码段之间的跳转 http://blog.csdn.net/zgh1988/article/details/7262901

全面剖析《自己动手写操作系统》第三章---分页机制 http://blog.csdn.net/zgh1988/article/details/7270748

全面剖析《自己动手写操作系统》第三章---中断机制 http://blog.csdn.net/zgh1988/article/details/7276259

全面剖析《自己动手写操作系统》第二章http://blog.csdn.net/zgh1988/article/details/7062065

全面剖析《自己动手写操作系统》第一章http://blog.csdn.net/zgh1988/article/details/7060032

《自己动手写操作系统》读后感http://blog.csdn.net/zgh1988/article/details/7059936




推荐阅读
  • 编写一个简单的内核驱动模块时报错 “/lib/modules/3.13.032generic/bulid: 没有那个文件或目录。 停止。”...
    编写一个简单的内核驱动模块1staticinthello_init()2{3printk(“hello,Iaminkernelnow\n”);4return0;5}6voidadd ... [详细]
  • 1.      准备工作: 程序:MinGW-3.1.0-1.exe     windows下的gcc,编译c语言的工具下载地址: http:umn.dl.sourceforge. ... [详细]
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 本文介绍了Java调用Windows下某些程序的方法,包括调用可执行程序和批处理命令。针对Java不支持直接调用批处理文件的问题,提供了一种将批处理文件转换为可执行文件的解决方案。介绍了使用Quick Batch File Compiler将批处理脚本编译为EXE文件,并通过Java调用可执行文件的方法。详细介绍了编译和反编译的步骤,以及调用方法的示例代码。 ... [详细]
  • 32位ubuntu编译android studio,32位Ubuntu编译Android 4.0.4问题
    问题一:在32位Ubuntu12.04上编译Android4.0.4源码时,出现了关于emulator的错误,关键是其Makefile里的 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
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社区 版权所有