顺德技术支持 骏域网站建设专家,开企网站建设,网络培训机构排名前十,肇庆 网站建设#x1f308;环境变量
#x1f344;初识 系统带的命令可以直接运行#xff08;ls ll命令等#xff09;#xff0c;但是我们自己写的命令必须要带上路径才能运行#xff08;./myproc#xff09;#xff0c;这是什么原因导致的#xff1f;如果我们也想自己写的命令直接…
环境变量
初识 系统带的命令可以直接运行ls ll命令等但是我们自己写的命令必须要带上路径才能运行./myproc这是什么原因导致的如果我们也想自己写的命令直接运行不带路径怎么搞 ----接下来揭晓答案 用ll明了直接显示处理三个文件。但是要运行我们自己创建的文件就要带上目录这些就和环境变量有关。
看环境变量内容
echo $PATH //显示操作系统搜索可执行文件的路径 可以看到环境变量PATH当中有多条路径这些路径由冒号隔开当你使用ls命令时系统就会查看环境变量PATH然后默认从左到右依次在各个路径当中进行查找。 像上面的ls命令啥的都在环境变量中储存了相应路径。
设置自己的环境变量
这里我们也可以将自己写的命令设置成环境变量一般有两种做法这里我只推荐一种。 将我们的命令复制到环境变量下 pwd查看变量路径将路径复制到环境变量路径set PATH$PATH复制的路径echo $PATH,如果目录上没有就把2命令的set换成export再来一遍就行了。 常见的环境变量 PATH用于指定系统中可执行文件的路径当你在命令行中输入一个命令时系统会在 PATH 变量指定的路径中查找该命令的可执行文件。 HOME用于指定当前用户的主目录路径。 USER用于指定当前用户名。 SHELL用于指定当前用户所使用的 Shell 程序路径。 对于 Linux 操作系统下面是一些常用的环境变量命令 env显示当前所有环境变量。export varvalue设置一个环境变量。echo $var显示一个环境变量的值。echo $PATH显示当前的 PATH 环境变量设置。export PATH$PATH:new_path在 PATH 环境变量中添加一个新的路径。clear清除屏幕上的输出。exit关闭当前的终端窗口。 环境变量对进程的作用 环境变量对进程的作用非常重要因为它们提供了进程可以访问的信息和资源包括但不限于以下内容 系统配置信息例如PATH环境变量包含了可执行文件的路径列表进程可以通过访问该变量来查找和执行命令。 用户信息例如HOME环境变量包含了当前用户的家目录路径进程可以通过访问该变量来获取用户的工作目录。 语言和区域设置例如LANG环境变量包含了当前系统的语言设置进程可以通过访问该变量来确定如何显示和处理文本数据。 总之环境变量是进程与操作系统之间进行通信和协作的一种重要方式。它们为进程提供了必要的信息和资源使得进程能够正常运行和完成任务。 程序地址空间
程序地址空间指的是一个进程在运行时所使用的虚拟内存空间。在现代操作系统中每个进程都被分配了一个独立的虚拟地址空间该空间包含了程序的代码、数据、堆栈等部分。
程序地址空间通常被分为以下几个部分 代码段text segment包含程序的机器指令通常是只读的。 数据段data segment包含程序中已经被初始化的全局变量和静态变量。 BSS段bss segment包含程序中未被初始化的全局变量和静态变量其值通常为0。 堆heap包含由程序在运行时动态分配的内存通常是由调用malloc等函数分配的。 栈stack包含函数调用时的局部变量、函数参数以及函数返回地址等信息。 程序地址空间在虚拟内存中需要由操作系统管理操作系统为每个进程分配一段独立的虚拟地址空间并映射到物理内存中以便程序能够访问所需的内存。操作系统还提供了一些系统调用使得进程可以动态地请求更多的内存或者释放已经不需要的内存。 在这个代码中变量a是第一个被定义的因此它被分配了最高的地址。变量b是第二个被定义的因此它被分配在a的下方。同样变量c是第三个被定义的因此它被分配在b的下方。因此这些变量在栈上的地址大小应该是按照以下顺序分配的 变量a最高的地址地址值最大。栈底变量b次高的地址地址值稍小于a的地址。变量c最低的地址地址值最小。栈顶 这个栈是倒着放的不是我们固定思维的正放。 接下来再看一个代码
#includestdio.h
#includestring.h
#includestdlib.h
#includeunistd.hint un_g_val; //未初始化全局变量int g_val 100; //初始化全局变量int main(int argc, char *argv[]){printf(text: %p\n, main);printf(uninit: %p\n, un_g_val);printf(init: %p\n, g_val);char* p (char*)malloc(16); printf(heap: % p\n, p); //堆printf(stack:%p\n, p); //栈return 0;}这个代码就验证了上面地址的情况注意我写的未初始化全局区和已初始化全局区的顺序错了所以地址才不是连续增大的。 接下来我们 我们看一段代码 #include stdio.h
#include unistd.h
#include stdlib.h
int g_val 0;
int main()
{pid_t id fork();if(id 0){perror(fork);return 0;}else if(id 0){ //child,子进程肯定先跑完也就是子进程先修改完成之后父进程再读取g_val100;printf(child[%d]: %d : %p\n, getpid(), g_val, g_val);}else{ //parentsleep(3);printf(parent[%d]: %d : %p\n, getpid(), g_val, g_val);}sleep(1);return 0;
}两者输入的内容不一样但是地址确实一样的那说明啥他们肯定不是存在物理内存上。如果存的物理地址一样那这个地址存的内容必定一样。就比如从学校回家。今天可以做1路汽车在少年宫下然后转2路到家。你也可以坐66路公交到天涯海角栈在坐666路到家。所以他们一定不是存在物理内存。而是存在虚拟地址上 进程地址空间不是物理地址 铁汁们进程地址空间不是实际上的物理地址而是虚拟的地址。所以原来我们在C语言学的地址空间也不是真正意义上的物理地址。 进程地址空间通常是虚拟地址空间而不是物理地址空间。在操作系统中每个进程都有自己的地址空间其中包含该进程的代码、数据和堆栈等。这个地址空间是虚拟的因为它只是一个进程视为自己的地址空间而不是实际的物理地址空间。当进程在执行时它的虚拟地址需要被映射到实际的物理地址。这个映射由操作系统内核中的内存管理单元MMU完成它将进程的虚拟地址转换为对应的物理地址。这个转换是透明的因此进程可以像它正在访问实际物理内存一样访问它的虚拟地址空间。总之进程的地址空间是虚拟地址空间需要通过内存管理单元将其映射到物理地址空间才能在实际的硬件上执行。以前学的地址都不是物理地址全部都是虚拟地址。 进程地址空间 每一个进程在创建后操作系统就会给他配置一个虚拟地址用来存放这个进程的内容。进程地址空间的本质也是内核的一种数据结构和PCB相似。在Linux当中进程地址空间具体由结构体mm_struct实现。进程地址空间就类似于一把尺子尺子的刻度由0x00000000到0xffffffff尺子按照刻度被划分为各个区域例如代码区、堆区、栈区等。而在结构体mm_struct当中便记录了各个边界刻度例如代码区的开始刻度与结束刻度如下图所示 而想把进程地址空间和物理空间进行联系起来需要用到一个介质页表也是一种数据结构虚拟地址通过页表的映射存储到物理内存的不同地方。到这里肯定有很多疑问别急我们来一一讲解。 为什么不是直接存到物理地址 内存管理的需要操作系统需要对内存进行管理包括内存的分配、释放、保护和共享等。如果让进程直接存在物理内存就会给内存管理带来很大的困难而虚拟地址空间可以方便地进行内存管理。 多道程序设计的需要现代操作系统通常支持多道程序设计这意味着多个进程可以同时运行在计算机上。如果让进程直接存在物理内存就会导致不同进程之间的内存冲突和资源竞争从而影响系统的正常运行。 内存保护的需要操作系统需要保护系统的内存不被未经授权的进程访问和破坏。如果让进程直接存在物理内存就很难进行内存保护而虚拟地址空间可以为每个进程分配独立的地址空间从而实现内存保护。 内存利用率的需要直接存到物理内存会导致物理内存的使用不充分出现碎片化现象。 给进程虚拟地址空间的好处 提高内存利用率虚拟地址空间允许多个进程共享同一块物理内存从而提高内存利用率。当一个进程需要更多的内存时操作系统可以动态地为其分配更多的虚拟地址空间而不必实际增加物理内存的大小。 实现内存保护虚拟地址空间可以为每个进程分配单独的地址空间从而防止进程相互干扰或破坏。操作系统可以利用内存保护机制来确保每个进程只能访问其分配的虚拟地址空间从而保护系统的安全性和稳定性。 支持多道程序设计虚拟地址空间支持多道程序设计使得多个进程可以在同一时间运行。每个进程都可以拥有自己的地址空间从而避免了不同进程之间的地址冲突和资源竞争确保了系统的正常运行。 支持动态链接库虚拟地址空间还可以支持动态链接库这使得多个进程可以共享同一份库文件从而减少了内存使用和磁盘空间的占用。 便于内存管理虚拟地址空间的使用使得操作系统可以更方便地进行内存管理。 虚拟地址空间和物理内存的链接 虚拟地址要想和物理内存联系起来就需要一种内核数据结构----页表。 为什么会有页表 如果这个进程是错误的那它的虚拟地址写到物理内存上后操作系统无法正确读取这个信息相当于浪费了很多不必要的空间。其次进程这么多这个虚拟地址映射到这里那个映射到那里。如果我们像运行这个进程那咋去找到它?所以操作系统需要记录下每一个进程存在的位置。 所以进程的作用 内存管理页表可以将虚拟地址空间划分为固定大小的页每个页对应着一段连续的物理内存区域。这样一来多个进程可以共享同一块物理内存而不需要每个进程都分配独立的物理内存空间。 虚拟化页表实现了虚拟内存的概念使得进程可以在自己的虚拟地址空间中执行而不需要考虑物理内存的具体细节。这样一来操作系统可以更加灵活地管理内存资源从而提高系统的整体性能和稳定性。 动态分配当一个进程需要更多的内存时操作系统可以动态地为其分配新的虚拟地址空间并将其映射到物理内存上而不需要为其分配新的物理内存空间。反之当一个进程不再需要某个虚拟地址空间时操作系统可以将其对应的物理内存释放并将虚拟地址空间与物理内存之间的映射关系删除以便于更好地利用内存资源。 内存保护页表还可以提供一些额外的保护和安全特性如权限控制、内存保护等。例如操作系统可以将某些页面标记为只读从而防止程序对其进行写入操作保护系统的稳定性和安全性。 写时拷贝
我们再回到上面那个奇怪的代码为啥父子进程的物理内存一样但是内容却不一样
这里就用到了一门新技术写时拷贝 写时拷贝Copy-On-WriteCOW是一种优化技术用于优化在进程复制时涉及的内存使用。在写时拷贝技术中操作系统在内存中为子进程创建一个共享原始内存区域的虚拟副本而不是创建一个完整的父进程物理副本。写时拷贝技术的主要优点是可以避免在进程复制时产生额外的物理内存开销。因为新进程与原始进程共享相同的物理内存页面所以只有在其中一个进程需要修改这些页面时才会产生额外的物理内存开销。如果说无脑为子进程创建父进程的副本那子进程的很多代码和数据用不到就会造成资源和空间的浪费。所以写时拷贝非常不错。 写时拷贝的优点 节省内存开销写时拷贝技术可以在进程复制时避免不必要的物理内存开销。因为新进程与原始进程共享相同的物理内存页面所以只有在其中一个进程需要修改这些页面时才会产生额外的物理内存开销。 提高程序运行效率写时拷贝技术可以提高程序的运行效率因为它避免了不必要的物理内存拷贝。如果进程在复制时需要完全复制物理内存那么进程复制的时间和开销将会很大。使用写时拷贝技术操作系统只需要复制虚拟地址空间的页表条目而不需要真正复制整个物理内存页面因此可以节省很多时间和资源。 保护数据安全写时拷贝技术可以保护原始数据的安全性。因为新进程与原始进程共享相同的物理内存页面所以当一个进程对共享页面进行写操作时它不会影响到原始进程的数据。这可以避免数据的意外修改和损坏。 支持共享内存写时拷贝技术支持共享内存使得多个进程可以共享同一块物理内存区域。如果没有写时拷贝技术共享内存将会很困难因为多个进程可能会同时修改同一块物理内存导致数据的混乱和错误。而使用写时拷贝技术多个进程可以共享相同的物理内存页面并且只有在其中一个进程需要修改页面时才会发生复制从而保证了共享内存的正确性和安全性。 所以我们再分析上面的代码 刚开始父进程拷贝了一个子进程然后父与子进程共享数据和代码。后面子进程的全局变量g_val修改修改后的全局变量区映射到页表的其他地方然后页表又映射到 物理内存的其他位置。所以才会出现地址相同但是打印的结果不同。这里通过写时拷贝把修改后的子进程虚拟地址给页表。而不是子进程完全复制一份父进程。物理地址肯定是发生改变的那个不变的地址是虚拟地址别搞混虚拟地址和物理地址。 注意之所以页表映射有蓝色有红色是因为不同内容要存在不同地方。全局变量存在已初始化全局区。函数等存在栈区等等所以有蓝色有红色 。
进程终止
进程退出的场景 代码运行完毕 结果正确------皆大欢喜代码运行完毕结果错误------- 小小失落代码异常终止------挠头抓耳 进程终止是指进程的运行被终止或者结束。进程终止可以是正常的结束也可以是异常的终止。正常的结束通常是指进程完成了它的任务或者根据某些条件主动地调用了系统调用来终止自己。在这种情况下操作系统会释放进程所占用的资源并将进程从系统中移除。而异常的终止则是指进程在执行过程中出现了错误或者被强制终止。例如进程访问了不存在的内存地址或者收到了操作系统发出的信号来强制终止。在这种情况下操作系统会立即中止进程的执行并回收进程所占用的资源。 进程退出码
echo $?
#includestdio.h
#includestdlib.hint main()
{printf(hello world!);return 0;
} 0就表示进程正常退出如果是非0值代表的进程异常退出并且这个值还代表这个进程所报错误。可以通过strerror来看错误码
#includestdio.h
#includestring.hint main()
{int i0; //有的编译器不支持把i0写道for里面for(i;i150;i){printf(%d:%s\n,i, strerror(i)); }return 0;
}如果我们随便输入一个命令 进程正常退出
return退出
在函数中我们经常都是return 0 这个就告诉函数程序执行完要退出了。但是要想要想进程退出那就不能用它了。
exit/_exit退出
如果我们想让进程退出那我们就要用到其他的函数exit, _exit。
exit函数 使用exit函数退出进程也是我们常用的方法exit函数可以在代码中的任何地方退出进程并且exit函数在退出进程前会做一系列工作 执行用户通过atexit或on_exit定义的清理函数。关闭所有打开的流所有的缓存数据均被写入。调用_exit函数终止进程。 这个细节就是在执行exit进行退出时编译器打印了上面的命令 I am a precess!.注意下面操作 _exit
这个不常用相比exit,但是我们可以了解一下_exit函数也可以在代码中的任何地方退出进程但是_exit函数会直接终止进程并不会在退出进程前会做任何收尾工作。
我们把前面的代码稍微修改一下即可 return exit, _exit区别 return 语句用于函数返回一个值并将控制流程返回到调用该函数的地方。exit() 函数用于终止程序的运行并返回到操作系统它会在退出之前执行所有必要的清理操作例如关闭打开的文件、释放内存等。在调用 exit() 函数之前程序可以正常地执行所有必要的操作因此 exit() 函数是安全的程序退出方式。_exit() 函数与 exit() 函数类似都用于终止程序的运行并返回到操作系统但它会立即退出程序不会执行任何清理操作这可能会导致数据损坏或资源泄漏等问题。因此除非必须要立即退出程序且不需要进行清理操作否则应该使用 exit() 函数。 进程等待
什么是为啥有 进程等待是指父进程在创建子进程后通过调用 wait() 或 waitpid() 等函数等待子进程结束并获取子进程的退出状态。进程等待的主要目的是让父进程能够控制子进程的执行顺序并在必要时对子进程进行处理。 进程等待的必要性 获取子进程退出状态进程等待还可以让父进程获取子进程的退出状态这对于调试和排错非常有用。父进程可以根据子进程的退出状态来判断子进程是否正常退出以及出错的原因。控制子进程执行顺序如果父进程需要等待多个子进程执行完毕后再进行后续操作那么可以使用进程等待来控制子进程的执行顺序。父进程可以在需要等待的地方调用 wait() 或 waitpid() 函数以确保子进程已经执行完毕。避免子进程成为僵尸进程如果父进程没有及时处理子进程的退出状态那么子进程就会成为僵尸进程占用系统资源并导致一些问题。通过进程等待父进程可以及时处理子进程的退出状态避免出现僵尸进程。 进程等待的方法
wait等待
wait()是一个系统调用用于等待子进程结束并获取子进程的退出状态。它的原型如下
#include sys/types.h
#include sys/wait.hpid_t wait(int *status);wait() 函数的返回值是子进程的进程号如果出错则返回 -1。如果父进程没有子进程那么 wait() 函数会立即返回。 wait() 函数的参数 status 是一个整型指针用于存储子进程的退出状态。如果子进程正常结束它的退出状态会被存储在 status 中父进程可以通过 WIFEXITED(status) 和 WEXITSTATUS(status) 宏来获取子进程的退出状态。如果子进程异常结束例如被信号终止那么 status 中存储的是一个描述异常结束原因的信号值。
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.h
int main()
{pid_t id fork();if(id 0){//childint count 10;while(count--){printf(I am child...PID:%d, PPID:%d\n, getpid(), getppid());sleep(1);}exit(0);}//fatherint status 0;pid_t ret wait(status);if(ret 0){//wait successprintf(wait child success...\n);if(WIFEXITED(status)){//exit normalprintf(exit code:%d\n, WEXITSTATUS(status));}}sleep(3);return 0;
}我们用这个脚本
while :; do ps axj | head -1 ps axj | grep proc | grep -v grep;echo ######################;sleep 1;done waitpid等待
waitpid是一个系统调用函数它用于等待指定进程的状态改变例如进程终止或暂停等。waitpid允许父进程等待它的一个子进程的状态改变而不必阻塞整个进程。这使得父进程能够同时等待多个子进程的状态改变。
函数原型
pid_t waitpid(pid_t pid, int *status, int options);pid参数指定要等待的进程的进程ID如果指定为-1则等待任何子进程。status参数是一个整数指针用于存储子进程的退出状态或其他信息。options参数用于指定等待的进程状态如WNOHANG选项表示在没有状态改变的情况下立即返回而不是阻塞等待状态改变。 当waitpid成功时返回终止或暂停进程的进程ID如果没有进程处于指定状态则返回0。如果出错则返回-1。 请注意waitpid只能等待子进程的状态改变如果要等待其他进程的状态改变可以使用其他函数如wait和waitid。 #include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.h
int main()
{pid_t id fork();if (id 0){//child int count 10;while (count--){printf(I am child...PID:%d, PPID:%d\n, getpid(), getppid());sleep(1);}exit(0);}//father int status 0;pid_t ret waitpid(id, status, 0);if (ret 0){//wait success printf(wait child success...\n);if (WIFEXITED(status)){//exit normal printf(exit code:%d\n, WEXITSTATUS(status));}else{//signal killed printf(killed by siganl %d\n, status 0x7F);}}sleep(3);return 0;
}#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.h
int main()
{pid_t id fork();if (id 0){int count 10;while (count--){printf(I am child...PID:%d, PPID:%d\n, getpid(), getppid());sleep(1);}exit(0);}int status 0;pid_t ret waitpid(id, status, 0);if (ret 0){printf(wait child success...\n);if (WIFEXITED(status)){printf(exit code:%d\n, WEXITSTATUS(status));}else{printf(killed by siganl %d\n, status 0x7F);}}sleep(3);return 0;
}在父进程运行过程中我们可以尝试使用kill -9命令将子进程杀死这时父进程也能等待子进程成功。 但是被信号杀死而退出的进程其退出码将没有意义。
获取子进程status
wait, waitpid函数都有statusstatus存的是进程的状态。如果传递NULL表示不关心子进程的退出状态信息。否则操作系统会根据该参数将子进程的退出信息反馈给父进程。status不能简单的当作整形来看待可以当作位图来看待具体细节如下图只研究status低16比特位
在status的低16比特位当中高8位表示进程的退出状态即退出码。进程若是被信号所杀则低7位表示终止信号而第8位比特位是core dump标志。 如果我们想得到进程的退出码和退出信号就可以使用位运算
exitCode (status 8) 0xFF; //退出码
exitSignal status 0x7F; //退出信号
对于此系统当中提供了两个宏来获取退出码和退出信号。
WIFEXITED(status)用于查看进程是否是正常退出本质是检查是否收到信号。WEXITSTATUS(status)用于获取进程的退出码。
exitNormal WIFEXITED(status); //是否正常退出
exitCode WEXITSTATUS(status); //获取退出码
需要注意的是当一个进程非正常退出时说明该进程是被信号所杀那么该进程的退出码也就没有意义了。 wait和waitpid的区别
wait函数会等待任何子进程结束并获取其退出状态而waitpid函数只会等待指定的子进程结束并获取其退出状态。wait函数没有提供获取子进程终止原因的选项而waitpid函数可以通过指定选项来获取子进程的终止原因例如被信号终止还是正常退出。
waitpid函数的原型为
pid_t waitpid(pid_t pid, int *status, int options);
其中pid参数指定要等待的子进程的PID。如果pid为-1则等待任何子进程结束。status参数用于存储子进程的退出状态。options参数可以指定等待子进程的行为例如是否阻塞等待、是否只等待被特定信号中断的子进程等等。
wait函数的原型为
pid_t wait(int *status);
其中status参数用于存储子进程的退出状态。
如果没有子进程在运行wait函数会阻塞程序直到有子进程结束为止而waitpid函数可以通过指定WNOHANG选项来避免阻塞。如果子进程已经结束wait函数和waitpid函数都会立即返回且获取到子进程的退出状态。如果子进程尚未结束wait函数和waitpid函数都会等待子进程结束并获取其退出状态。在多进程程序中waitpid函数可以通过指定pid参数来等待特定的子进程结束。如果不指定pid参数或pid为-1则等待任何子进程结束。在使用这些函数时需要注意避免出现僵尸进程即已经结束但父进程尚未调用wait或waitpid来获取退出状态的子进程。可以使用信号处理函数或者使用waitpid函数中的WNOHANG选项来避免出现僵尸进程。 文章转载自: http://www.morning.kpbq.cn.gov.cn.kpbq.cn http://www.morning.dmldp.cn.gov.cn.dmldp.cn http://www.morning.rtbj.cn.gov.cn.rtbj.cn http://www.morning.dmxzd.cn.gov.cn.dmxzd.cn http://www.morning.pbmkh.cn.gov.cn.pbmkh.cn http://www.morning.nwnbq.cn.gov.cn.nwnbq.cn http://www.morning.qkbwd.cn.gov.cn.qkbwd.cn http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn http://www.morning.rymb.cn.gov.cn.rymb.cn http://www.morning.krqhw.cn.gov.cn.krqhw.cn http://www.morning.sfnr.cn.gov.cn.sfnr.cn http://www.morning.qphcq.cn.gov.cn.qphcq.cn http://www.morning.dmzmy.cn.gov.cn.dmzmy.cn http://www.morning.lkrmp.cn.gov.cn.lkrmp.cn http://www.morning.nbgfz.cn.gov.cn.nbgfz.cn http://www.morning.rjxwq.cn.gov.cn.rjxwq.cn http://www.morning.sdkaiyu.com.gov.cn.sdkaiyu.com http://www.morning.bzjpn.cn.gov.cn.bzjpn.cn http://www.morning.rdsst.cn.gov.cn.rdsst.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.cfnsn.cn.gov.cn.cfnsn.cn http://www.morning.sfhjx.cn.gov.cn.sfhjx.cn http://www.morning.jxfmn.cn.gov.cn.jxfmn.cn http://www.morning.jntcr.cn.gov.cn.jntcr.cn http://www.morning.qzpw.cn.gov.cn.qzpw.cn http://www.morning.ggmls.cn.gov.cn.ggmls.cn http://www.morning.tcylt.cn.gov.cn.tcylt.cn http://www.morning.yqmmh.cn.gov.cn.yqmmh.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.zdmlt.cn.gov.cn.zdmlt.cn http://www.morning.lrwsk.cn.gov.cn.lrwsk.cn http://www.morning.ksqyj.cn.gov.cn.ksqyj.cn http://www.morning.pqfbk.cn.gov.cn.pqfbk.cn http://www.morning.qpntn.cn.gov.cn.qpntn.cn http://www.morning.dpwcl.cn.gov.cn.dpwcl.cn http://www.morning.mxftp.com.gov.cn.mxftp.com http://www.morning.lgqdl.cn.gov.cn.lgqdl.cn http://www.morning.nqfxq.cn.gov.cn.nqfxq.cn http://www.morning.zmyhn.cn.gov.cn.zmyhn.cn http://www.morning.mwwnz.cn.gov.cn.mwwnz.cn http://www.morning.lwrcg.cn.gov.cn.lwrcg.cn http://www.morning.pshtf.cn.gov.cn.pshtf.cn http://www.morning.lynmt.cn.gov.cn.lynmt.cn http://www.morning.xgzwj.cn.gov.cn.xgzwj.cn http://www.morning.rbgwj.cn.gov.cn.rbgwj.cn http://www.morning.nzwp.cn.gov.cn.nzwp.cn http://www.morning.hxlch.cn.gov.cn.hxlch.cn http://www.morning.pmmrb.cn.gov.cn.pmmrb.cn http://www.morning.ndxss.cn.gov.cn.ndxss.cn http://www.morning.nbqwt.cn.gov.cn.nbqwt.cn http://www.morning.bncrx.cn.gov.cn.bncrx.cn http://www.morning.rxfgh.cn.gov.cn.rxfgh.cn http://www.morning.sblgt.cn.gov.cn.sblgt.cn http://www.morning.rrxnz.cn.gov.cn.rrxnz.cn http://www.morning.dwfxl.cn.gov.cn.dwfxl.cn http://www.morning.rgrz.cn.gov.cn.rgrz.cn http://www.morning.qxmys.cn.gov.cn.qxmys.cn http://www.morning.fesiy.com.gov.cn.fesiy.com http://www.morning.hytr.cn.gov.cn.hytr.cn http://www.morning.xlyt.cn.gov.cn.xlyt.cn http://www.morning.rtsdz.cn.gov.cn.rtsdz.cn http://www.morning.bfcrp.cn.gov.cn.bfcrp.cn http://www.morning.yxmcx.cn.gov.cn.yxmcx.cn http://www.morning.wrqw.cn.gov.cn.wrqw.cn http://www.morning.rntgy.cn.gov.cn.rntgy.cn http://www.morning.htbgz.cn.gov.cn.htbgz.cn http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn http://www.morning.xqjh.cn.gov.cn.xqjh.cn http://www.morning.ryznd.cn.gov.cn.ryznd.cn http://www.morning.ktfnj.cn.gov.cn.ktfnj.cn http://www.morning.gbfuy28.cn.gov.cn.gbfuy28.cn http://www.morning.yghlr.cn.gov.cn.yghlr.cn http://www.morning.tdttz.cn.gov.cn.tdttz.cn http://www.morning.khntd.cn.gov.cn.khntd.cn http://www.morning.lwxsy.cn.gov.cn.lwxsy.cn http://www.morning.kscwt.cn.gov.cn.kscwt.cn http://www.morning.nffwl.cn.gov.cn.nffwl.cn http://www.morning.xfxqj.cn.gov.cn.xfxqj.cn http://www.morning.mmplj.cn.gov.cn.mmplj.cn http://www.morning.ptysj.cn.gov.cn.ptysj.cn