存档在 2012年8月

const char*与char* const修改值的权限

2012年8月28日

const char*类型的指针(指向常量的指针)其所指向的内容是常量,是不可以修改的,但其指针值是可以修改的。

但对于char* const类型的指针(常量指针)来说,它的地址是一个常量,也就是说,它的指针值是常量,不可以修改,但其指向的内容是可以修改的。

Linux进程的状态

2012年8月28日

我们先看Linux的进程五态模型及其转换:

这些状态是task_struct结构的一部分:

 

1  R (task_running) : 可执行状态

只有在该状态的进程才可能在CPU上运行。而同一时刻可能有多个进程 处于可执行状态,这些进程的task_struct结构(进程控制块)被放入对应CPU的 可执行队列中(一个进程最多只能出现在一个CPU的可执行队列中)。进程调度器的任务就是从各个CPU的可执行队列中分别选择一个进程在该CPU上运行。

很多操作系统教科书将正在CPU上执行的进程定义为RUNNING状态、而将可执行但是尚未被调度执行的进程定义为READY状态,这两种状态在linux下统一为 TASK_RUNNING状态。

2  S (task_interruptible): 可中断的睡眠状态

处于这个状态的进程因为等待某某事件的发生(比如等待socket连 接、等待信号量),而被挂起。这些进程的task_struct结构被放入对应事件的等待队列中。当这些事件发生时(由外部中断触发、或由其他进程触发),对应的等 待队列中的一个或多个进程将被唤醒。

通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程都处于task_interruptible状态(除非机器的负载很高)。毕竟CPU就这么一两个,进程动辄几十上百个,如果不是绝大多数进程都在睡眠,CPU又怎么响应得过来。

3  D (task_uninterruptible): 不可中断的睡眠状态

与task_interruptible状态类似,进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指的并不是CPU不响应外部硬件的中断,而是指进程不响应异步信号。
绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的。但是uninterruptible sleep 状态的进程不接受外来的任何信号,因此无法用kill杀掉这些处于D状态的进程,无论是”kill”, “kill -9″还是”kill -15″,这种情况下,一个可选的方法就是reboot。

处于uninterruptible sleep状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就被ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统已经不可访问了.

而task_uninterruptible状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。

在进程对某些硬件进行操作时(比如进程调用read系统调用对某个设 备文件进行读操作,而read系统调用最终执行到对应设备驱动的代码,并与对应的物理设备进行交互),可能需要使用task_uninterruptible状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的状态。这种情况下的task_uninterruptible状态总是非常短暂的,通过ps命 令基本上不可能捕捉到。

我们通过vmstat 命令中procs下的b 可以来查看是否有处于uninterruptible 状态的进程。该命令只能显示数量。

4  T(task_stoppedor task_traced):暂停状态或跟踪状态

向进程发送一个sigstop信号,它就会因响应该信号而进入task_stopped状态(除非该进程本身处于task_uninterruptible状态而不响应信号)。(sigstop与sigkill信号一样,是非常强制的。不允许用户进程通过signal系列的系统调用重新设置对应的信号处理函数。)
向进程发送一个sigcont信号,可以让其从task_stopped状态恢复到task_running状态。

当进程正在被跟踪时,它处于task_traced这个特殊的状态。“正 在被跟踪”指的是进程暂停下来,等待跟踪它的进程对它进行操作。比如在gdb中对被跟踪的进程下一个断点,进程在断点处停下来的时候就处于task_traced状态。而在其他时候,被跟踪的进程还是处于前面提到的那些状态。

对于进程本身来说,task_stopped和task_traced状态很类似,都是表示进程暂停下来。
而task_traced状态相当于在task_stopped之上多了一层保护,处于task_traced状态的进程不能响应sigcont信号而被唤醒。只能等到调试进程通过ptrace系统调用执行ptrace_cont、ptrace_detach等操作(通过ptrace系统调用的参数指定操作),或调试进程退出,被调试的进程才能恢复task_running状态。

 5 Z (task_dead -exit_zombie):退出状态,进程成为僵尸进程

在Linux进程的状态中,僵尸进程是非常特殊的一种,它是已经结束了的进程,但是没有从进程表中删除。太多了会导致进程表里面条目满了,进而导致系统崩溃,倒是不占用其他系统资源。

它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在 进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。

进 程在退出的过程中,处于TASK_DEAD状态。在这个退出过程中,进程占有的所有资源将被回收,除了task_struct结构(以及少数资源)以外。于是进程就只剩 下task_struct这么个空壳,故称为僵尸。

之所以保留task_struct,是因为task_struct里面保存了进程的退出码、以及一些统计信息。而其父进程很可能会关心这些信息。比如在shell中,$?变量就保存了最后一个退出的前台进程的退出码,而这个退出码往往被作为if语句的判断条件。
当然,内核也可以将这些信息保存在别的地方,而将task_struct结构释放掉,以节省一些空间。但是使用task_struct结构更为方便,因为在内核中已经建立了从pid到task_struct查找关系,还有进程间的父子关系。释放掉task_struct,则需要建立一些新的数据结构,以便让父进程找到它的子进程的退出信息。

子进程在退出的过程中,内核会给其父进程发送一个信号,通知父进程来“收 尸”。父进程可以通过wait系列的系统调用(如wait4、waitid)来等待某个或某些子进程的退出,并获取它的退出信息。然后wait系列的系统调用会顺便将子进程的尸体(task_struct)也释放掉。

这 个信号默认是SIGCHLD,但是在通过clone系统调用创建 子进程时,可以设置这个信号。

如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,那么它就一直保持僵尸状态,子进程的尸体(task_struct)也就无法释放掉。

如果这时父进程结束了,那么init进程自动会接手这个子进程,为它收尸,它还是能被清除的。但是如果如果父进程是一个循环,不会结束, 那么子进程就会一直保持僵尸状态,这就是为什么系统中有时会有很多的僵尸进程。

当进程退出的时候,会将它的所有子进程都托管给别的进程(使之成为别的进程的子进程)。托管的进程可能是退出进程所在进程组的下一个进程(如果存在的话),或者是1号进程。所以每个进程、每时每刻都有父进程 存在。除非它是1号进程。1号进程,pid为1的进程,又称init进程。

C/C++编译器为什么要进行内存对齐处理

2012年8月28日

今天看到一段代码,关于内存对齐,所以总结一下,参考一下:
先看这段代码

class Base
{
private:
	double a1;
	double a2;
	double a3;

};
class Derived : public Base
{
private:
	int *p;
};
int main()
{
	cout<<sizeof Base<<endl;
	cout<<sizeof Derived<<endl;
	system("pause");
	return 0;
}

结果为:
24
28
3个doule共24字节。
理论上指针是4字节,但是实际上这个类对象达到28字节。
结果和下面一段代码相同:

class Base
{
private:
	double a1;
	double a2;
	double a3;

};
class Derived : public Base
{
private:
	int *p;
	int a;
};
int main()
{
	cout<<sizeof Base<<endl;
	cout<<sizeof Derived<<endl;
	system("pause");
	return 0;
}
派生类虽然增加了一个成员a,但是实际上这个类对象所占用内存大小并不变化。

进行内存对齐的作用主要是有两个:
(1)平台移植。不是所有的硬件平台都能够访问任意地址上的数据,
(2)性能:内存对齐后访问速度提升了。
下面解释一下为什么内存对齐会提升效率。

CPU把内存当成是一块一块的,块的大小可以是2、4、8、16字节等大小。CPU在读取内存的时候是一块一块读取的。块大小即memory access granularity:内存读取粒度。

假设CPU要读取一个int型4字节大小的数据,看下列2种情况:
(1)数据从0字节开始;
(2)数据从1字节开始;
假设内存读取粒度是4.

情况(1)的时候,CPU只需一次便可把4字节读取出来。
但是情况(2)的时候,要复杂一些。这个时候CPU先访问一次内存,读取0-3字节进寄存器,再读取4-7字节进寄存器,然后把0、6、7、8字节的数据删除掉,最后合并1-4字节的数据。可以看出,如果内存没有对齐,所进行的操作要复杂得多。

尤其是,上面的这些操作也只是一部分CPU可以实现,即平台移植~~

总结为:

1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

const修饰类的成员函数与const修饰非成员函数,静态成员函数不能用const

2012年8月28日

在面向对象编程中,类是核心,也是基础,很多成员函数,为了不对成员变量修改,都会修饰成const,这是无可厚非的,但是你想没想过非成员函数是否可以用const修饰,为什么?

我想非成员函数是不能使用const修饰的,因为非成员函数不是属于某个对象,也不存在保护某个对象的成员变量被修改。而对象的成员函数都有个this指针作为参数,如果用const修饰成员函数,则代表着不能修改this指针指向的对象的任何成员。
如果你强制在非成员函数上使用const修饰,那么你得到的将会是“error C2270: “*”: 非成员函数上不允许修饰符”。
   static在c++中的第五种含义:用static修饰不访问非静态数据成员的类成员函数。这意味着一个静态成员函数只能访问它的参数、类的静态数据成员和全局变量。
   不能用const的原因:

     这是C++的规则,const修饰符用于表示函数不能修改成员变量的值,该函数必须是含有this指针的类成员函数,函数调用方式为thiscall,而类中的static函数本质上是全局函数,调用规约是__cdecl或__stdcall,不能用const来修饰它。一个静态成员函数访问的值是其参数、静态数据成员和全局变量,而这些数据都不是对象状态的一部分。而对成员函数中使用关键字const是表明:函数不会修改该函数访问的目标对象的数据成员。既然一个静态成员函数根本不访问非静态数据成员,那么就没必要使用const了。
   什么时候使用静态数据成员和静态函数呢?
      定义数据成员为静态变量,以表明此全局数据逻辑上属于该类。
      定义成员函数为静态函数,以表明此全局函数逻辑上属于该类,而且该函数只对静态数据、全局数据或者参数进行操作,而不对非静态数据成员进行操作。
   static的第一种含义:修饰全局变量时,表明一个全局变量只对定义在同一文件中的函数可见。
   static的第二种含义:修饰局部变量时,表明该变量的值不会因为函数终止而丢失。
   static的第三种含义:修饰函数时,表明该函数只在同一文件中调用。
   static的第四种含义:修饰类的数据成员,表明对该类所有对象这个数据成员都只有一个实例。即该实例归 所有对象共有。
   static的第五种含义:修饰类成员函数,如上。

串口助手高级版

2012年8月28日

提示:
1.所有版本都需要安装.net framework3.5, 如果你安装过VS,或者使用windos7等版本,则已经默认安装。
2.如果需要其他.net版本的安装软件,邮件联系我。
3.软件中有些地方抛出异常未catch,提示错误,选择忽略即可,将会在下一版本中修改。
4.软件自动检测到电脑可以使用的所有串口,如果没有识别,排除软件问题。
V1.6版本
1. 修复让GDI对象数上升的BUG
华军下载:http://www.onlinedown.net/soft/419619.htm
下载链接:http://pan.baidu.com/share/link?shareid=311552&uk=1645707199
V1.5版本
1. 修复一个BUG
2. 增加了按行的多彩显示
下载链接:http://pan.baidu.com/share/link?shareid=155673&uk=1645707199
预览:http://img2081.poco.cn/mypoco/my … 130107093824074.jpg
V1.4版本
1. 修改了按帧接收,可以设置帧的长度
2. 增加了暂停按钮
3. 增加了在线检测新版本
下载链接:http://pan.baidu.com/share/link?shareid=133915&uk=1645707199

分享时间:2012-12-12 17:33浏览次数:421转存次数:9下载次数:260
分享时间:2012-12-12 17:33浏览次数:316转存次数:6下载次数:214
分享时间:2012-12-12 17:33浏览次数:276转存次数:4下载次数:192
V1.3版本
修改了文本框收到数据后,不自动滚动到底部的BUG。
下载链接:请下载最新版本
按帧接收,由于没有校验和可能把数据数据当做帧头或者帧尾的缺点,后面再改进,可以用帧长来匹配。
V1.2版本
1. 修改了按组接收的一个BUG
2. 增加了串口缓冲区的清理
下载链接:请下载最新版本
V1.1版本
V1.0 较之V0.1
1. 增加了串口定时扫描功能。能自动检测到串口的增减,并自动显示。
2. 改进和增加了多处异常检测,更加稳定。
3. 增加图钉功能,用于置于顶层。
4. 增加按组接收功能,设置好每一次接收的字节数后自动接收。
5. 增加了退出提醒,防止误操作。
6. 增加了按帧接收功能,可以设置帧头帧尾来实现接收,功能更强大。
7. 增加了对选中的16进制数翻译成10进制数功能,并且对已经翻译的数着红色。
8. 优化了多线程读写功能,读取更加稳定可靠。
9. 修改了上一版中配置中心无校验的缺陷。
10. 优化自动换行功能,换行更快捷。
11. 对16进制数改进,可以加0x前缀,可以大小写都无所谓。
12. 发送的是链接可以加下划线。
下载链接:(推荐外部链接下载)
外部链接:【请下载最新版本】
V0.1版本
1.串口助手超级版可以做什么  
2.串口助手有哪些新功能?
   2.1. 自动换行                                                               
2.2. 随机发送帧
                                                                           
2.3. 设计一个可变帧发送                                                

2.4. 按组接收(下一版本增加)
2.5. 在收到的N多字节中,检索完整的数据帧(采用多线程编写,代码已经写好,还未整合,会在下一版本增加)
2.6. 囊括其他版本的所有功能。

3. 串口助手高级版主界面更加友好
下载:(推荐外部链接下载)【V0.1下载量综合各大下载站统计超过500次】
外部链接:【请下载最新版本】
————————————————————————————————————————————————–
下载量统计:
V1.1
浏览次数:108         浏览次数:128
转存次数:3           转存次数:3
下载次数:89          下载次数:115
分享时间:2012-12-3 19:21浏览次数:
220
转存次数:
8下载次数:
180下载量超过600
————————————————————————————————————————————————–
串口助手是工程中调试程序必备工具,往往在硬件没有做好之前就可以进行软调试。搭配VSPD可以实现本地调试任何关于串口的程序,异常方便。而平常的串口软件部支持换行,不支持自定义帧结构,令工作效率大大降低,串口助手高级版则弥补了这一缺点。

V1.5预览

C++ 的 _T()

2012年8月28日

_T(“”)是一个宏,他的作用是让你的程序支持Unicode编码,因为Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。

如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把”Hello”字符串以UNICODE方式保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。
LPSTR:32bit指针指向一个字符串,每个字符占1字节
LPCSTR:32-bit指针指向一个常字符串,每个字符占1字节
LPCTSTR:32-bit指针指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义
LPTSTR:32-bit指针每字符可能占1字节或2字节,取决于Unicode是否定义
L是表示字符串资源为Unicode的。
比如
wchar_t Str[] = L”Hello World!”;
这个就是双子节存储字符了。
_T是一个适配的宏~

#ifdef _UNICODE的时候
_T就是L
没有#ifdef _UNICODE的时候
_T就是ANSI的。
比如
LPTSTR lpStr = new TCHAR[32];
TCHAR* szBuf = _T(“Hello”);
以上两句使得无论是在UNICODE编译条件下都是正确编译的。
而且MS推荐你使用相匹配的字符串函数。
比如处理LPTSTR或者LPCTSTR 的时候,不要用strlen ,而是要用_tcslen
否则在UNICODE的编译条件下,strlen不能处理 wchar_t*的字符串。
T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()…),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集?编译的时候才决定

在linux下设置开机自动启动程序的方法

2012年8月28日

下面用自启动apache为例;
自启动脚本:
/usr/local/apache2/bin;
./apachectl start
文件位于/etc/rc.d/init.d下,名为apached, 注意要可执行.
#chmod +x /etc/rc.d/init.d/apached //设置文件的属性为可执行
#ln -s /etc/rc.d/init.d/apached /etc/rc3.d/S90apache //建立软连接,快捷方式
#ln -s /etc/rc.d/init.d/apached /etc/rc0.d/K20apache

 

在Red Hat Linux中自动运行程序
1.开机启动时自动运行程序
Linux加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程init。init根据配置文件继续引导过程,启动其它进程。通常情况下,修改放置在 /etc/rc或 /etc/rc.d 或 /etc/rc?.d 目录下的脚本文件,可以使init自动启动其它程序。例如:编辑 /etc/rc.d/rc.local 文件,在文件最末加上一行”xinit”或”startx”,可以在开机启动后直接进入X-Window。

2.登录时自动运行程序
用户登录时,bash首先自动执行系统管理员建立的全局登录script :/etc/profile。然后bash在用户起始目录下按顺序查找三个特殊文件中的一个:/.bash_profile、/.bash_login、 /.profile,但只执行最先找到的一个。
因此,只需根据实际需要在上述文件中加入命令就可以实现用户登录时自动运行某些程序(类似于DOS下的Autoexec.bat)。

3.退出登录时自动运行程序
退出登录时,bash自动执行个人的退出登录脚本/.bash_logout。例如,在/.bash_logout中加入命令”tar -cvzf c.source.tgz *.c”,则在每次退出登录时自动执行 “tar” 命令备份 *.c 文件。

4.定期自动运行程序
Linux有一个称为crond的守护程序,主要功能是周期性地检查 /var/spool/cron目录下的一组命令文件的内容,并在设定的时间执行这些文件中的命令。用户可以通过crontab 命令来建立、修改、删除这些命令文件。
例如,建立文件crondFile,内容为”00 9 23 Jan * HappyBirthday”,运行”crontab cronFile”命令后,每当元月23日上午9:00系统自动执行”HappyBirthday”的程序(”*”表示不管当天是星期几)。

5.定时自动运行程序一次
定时执行命令at 与crond 类似(但它只执行一次):命令在给定的时间执行,但不自动重复。at命令的一般格式为:at [ -f file ] time ,在指定的时间执行file文件中所给出的所有命令。也可直接从键盘输入命令:

$ at 12:00
at>mailto Roger -s ″Have a lunch″ < plan.txt
at>Ctr-D
Job 1 at 2000-11-09 12:00

2000-11-09 12:00时候自动发一标题为”Have a lunch”,内容为plan.txt文件内容的邮件给Roger。

 

#!/bin/bash
RESTART=”……..” #里面写相应服务代码
START=”…….”
STOP=”……….”
case “$1” in
restart)
$RESTART
echo “……”
;;
start)
$START
echo “……”
;;
STOP)
$STOP
echo “……”
;;
*)
echo “Usage: $0 {restart | start | stop}”
exit 1
esac

exit 1

脚本写完要修改一下权限 chmod u+x test.sh

 

首先,linux随机启动的服务程序都在/etc/init.d这个文件夹里,里面的文件全部都是脚本文件(脚本程 序简单的说就是把要运行的程序写 到一个 文件里让系统能够按顺序执行,类似windows下的autorun.dat文件),另外在/etc这个文件夹里还有诸如名为rc1.d, rc2.d一直到rc6.d的文件夹,这些都是linux不同的runlevel,我们一般进入的X windows多用户的运行级别是第5级,也就是rc5.d,在这个文件夹下的脚本文件就是运行第5级时要随机启动的服务程序。需要注意的是,在每个rc (1-6).d文件夹下的文件其实都是/etc/init.d文件夹下的文件的一个软连接(类似windows中的快捷方式),也就是说,在 /etc/init.d文件夹下是全部的服务程序,而每个rc(1-6).d只链接它自己启动需要的相应的服务程序!

要启动scim(某一程序),我们首先要知道scim程序在哪里,用locate命令可以找到,scim在/usr/bin/scim这里,其中usr表 示是 属于用户的,bin在linux里表示可以执行的程序。这样,我就可以编写一个脚本程序,把它放到/etc/init.d里,然后在rc5.d里做一个相 应的软链接就可以了。
这个脚本其实很简单,就两行:

#!/bin/bash
/usr/bin/scim

第一行是声明用什么终端运行这个脚本,第二行就是要运行的命令。

还需要注意的一点是,在rc5.d里,每个链接的名字都是以S或者K开头的,S开头的表示是系统启动是要随机启动的,K开头的是不随机启动的。这 样,你就可以知道,如果我要哪个服务随机启动,就把它名字第一个字母K改成S就可以了,当然,把S改成K后,这个服务就不能随机启动了。因此,我这个链接 还要起名为SXXX,这样系统才能让它随机启动。

虚拟机VMware3种网络模式(桥接、nat、Host-only)的工作原理

2012年8月28日

VMware网络配置详解一:三种网络模式简介

安装好虚拟机以后,在网络连接里面可以看到多了两块网卡:


其 中VMnet1是虚拟机Host-only模式的网络接口,VMnet8是NAT模式的网络接口,这些后面会详细介绍

选择虚拟机网络模 式方法如下,单击Edit virtual machine settings,如图所示:

然后在Hardware选项卡中选择Ethernet,在左边Network connection框架中有如下四个单选项:

1. Bridged(桥接模式)


在桥接模式下,VMware虚拟出来的操作系统就像是局域网中的一独立的主机,它可以访问网内任何一台机器不过你需要多于一个的IP地址,并且需要手工为 虚拟系统配置IP地址子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信

如果你想利用VMware在局域网内新建一个虚拟服务器,为局域网用户提供网络服务,就应该选择桥接模式

2. NAT(网络地址转换模式)


使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网也就是说,使用NAT模式可以实现在虚拟系统里访问互 联网NAT模式下的虚拟系统的TCP/IP配置信息是由VMnet8(NAT)虚拟网络的DHCP服务器提供的,无法进行手工修改,因此虚拟系统也就无法 和本局域网中的其他真实主机进行通讯采用NAT模式最大的优势是虚拟系统接入互联网非常简单,你不需要进行任何其他的配置,只需要宿主机器能访问互联网即 可

如果你想利用VMware安装一个新的虚拟系统,在虚拟系统中不用进行任何手工配置就能直接访问互联网,建议你采用NAT模式

3. Host-only(主机模式)


在某些特殊的网络调试环境中,要求将真实环境和虚拟环境隔离开,这时你就可采用Host-only模式在Host-only模式中,所有的虚拟系统是可以 相互通信的,但虚拟系统和真实的网络是被隔离开的可以利用Windows XP里面自带的Internet连接共享(实际上是一个简单的路由NAT)来让虚拟机 通过主机真实的网卡进行外网的访问虚拟系统的TCP/IP配置信息(如IP地址网关地址DNS服务器等),都是由VMnet1(Host-only)虚拟 网络的DHCP服务器来动态分配的。

如果你想利用VMware创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可以选择Host-only模式。

以上,就是 虚拟机VMware 3种网络模式(桥接、nat、Host-only)的工作原理。