幼儿饰品瑜伽美体用品微软
投稿投诉
微软创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品

深入理解Linux中进程控制(精讲)

  一、进程创建fork函数初识
  在Linux中,fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
  返回值:
  在子进程中返回0,父进程中返回子进程的PID,子进程创建失败返回1。
  进程调用fork,当控制转移到内核中的fork代码后,内核做:分配新的内存块和内核数据结构给子进程。将父进程部分数据结构内容拷贝至子进程。添加子进程到系统进程列表当中。fork返回,开始调度器调度。
  fork之后,父子进程代码共享。例如:
  运行结果如下:
  这里可以看到,Before只输出了一次,而After输出了两次。其中,Before是由父进程打印的,而调用fork函数之后打印的两个After,则分别由父进程和子进程两个进程执行。也就是说,fork之前父进程独立执行,而fork之后父子两个执行流分别执行。
  注意:fork之后,父进程和子进程谁先执行完全由调度器决定。fork函数返回值
  fork函数为什么要给子进程返回0,给父进程返回子进程的PID?
  一个父进程可以创建多个子进程,而一个子进程只能有一个父进程。因此,对于子进程来说,父进程是不需要被标识的;而对于父进程来说,子进程是需要被标识的,因为父进程创建子进程的目的是让其执行任务的,父进程只有知道了子进程的PID才能很好的对该子进程指派任务。
  为什么fork函数有两个返回值?
  父进程调用fork函数后,为了创建子进程,fork函数内部将会进行一系列操作,包括创建子进程的进程控制块、创建子进程的进程地址空间、创建子进程对应的页表等等。子进程创建完毕后,操作系统还需要将子进程的进程控制块添加到系统进程列表当中,此时子进程便创建完毕了。
  也就是说,在fork函数内部执行return语句之前,子进程就已经创建完毕了,那么之后的return语句不仅父进程需要执行,子进程也同样需要执行,这就是fork函数有两个返回值的原因。写时拷贝
  当子进程刚刚被创建时,子进程和父进程的数据和代码是共享的,即父子进程的代码和数据通过页表映射到物理内存的同一块空间。只有当父进程或子进程需要修改数据时,才将父进程的数据在内存当中拷贝一份,然后再进行修改。
  这种在需要进行数据修改时再进行拷贝的技术,称为写时拷贝技术。
  1、为什么数据要进行写时拷贝?
  进程具有独立性。多进程运行,需要独享各种资源,多进程运行期间互不干扰,不能让子进程的修改影响到父进程。
  2、为什么不在创建子进程的时候就进行数据的拷贝?
  子进程不一定会使用父进程的所有数据,并且在子进程不对数据进行写入的情况下,没有必要对数据进行拷贝,我们应该按需分配,在需要修改数据的时候再分配(延时分配),这样可以高效的使用内存空间。
  3、代码会不会进行写时拷贝?
  90的情况下是不会的,但这并不代表代码不能进行写时拷贝,例如在进行进程替换的时候,则需要进行代码的写时拷贝。
  相关视频推荐
  Linux内核进程状态详解
  linux内核,进程调度器的实现,完全公平调度器CFS
  5个方面分析linux内核架构(进程管理,内存管理,网络协议栈。。)
  需要CCLinux服务器架构师学习资料加qun812855908获取(资料包括CC,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCPIP,协程,DPDK,ffmpeg等),免费分享
  fork常规用法一个进程希望复制自己,使子进程同时执行不同的代码段。例如父进程等待客户端请求,生成子进程来处理请求。一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。fork调用失败的原因
  fork函数创建子进程也可能会失败,有以下两种情况:系统中有太多的进程,内存空间不足,子进程创建失败。实际用户的进程数超过了限制,子进程创建失败。二、进程终止进程退出场景
  进程退出只有三种情况:代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。进程退出码
  我们都知道main函数是代码的入口,但实际上main函数只是用户级别代码的入口,main函数也是被其他函数调用的,例如在VS2013当中main函数就是被一个名为tmainCRTStartup的函数所调用,而tmainCRTStartup函数又是通过加载器被操作系统所调用的,也就是说main函数是间接性被操作系统所调用的。
  既然main函数是间接性被操作系统所调用的,那么当main函数调用结束后就应该给操作系统返回相应的退出信息,而这个所谓的退出信息就是以退出码的形式作为main函数的返回值返回,我们一般以0表示代码成功执行完毕,以非0表示代码执行过程中出现错误,这就是为什么我们都在main函数的最后返回0的原因。
  当我们的代码运行起来就变成了进程,当进程结束后main函数的返回值实际上就是该进程的进程退出码,我们可以使用echo?命令查看最近一次进程退出的退出码信息。
  例如,对于下面这个简单的代码:
  代码运行结束后,我们可以查看该进程的进程退出码。〔clVM015centosprocTermination〕echo?
  这时便可以确定main函数是顺利执行完毕了。
  为什么以0表示代码执行成功,以非0表示代码执行错误?
  因为代码执行成功只有一种情况,成功了就是成功了,而代码执行错误却有多种原因,例如内存空间不足、非法访问以及栈溢出等等,我们就可以用这些非0的数字分别表示代码执行错误的原因。
  C语言当中的strerror函数可以通过错误码,获取该错误码在C语言当中对应的错误信息:
  运行代码后我们就可以看到各个错误码所对应的错误信息:
  实际上Linux中的ls、pwd等命令都是可执行程序,使用这些命令后我们也可以查看其对应的退出码。
  可以看到,这些命令成功执行后,其退出码也是0。
  但是命令执行错误后,其退出码就是非0的数字,该数字具体代表某一错误信息。
  注意:退出码都有对应的字符串含义,帮助用户确认执行失败的原因,而这些退出码具体代表什么含义是人为规定的,不同环境下相同的退出码的字符串含义可能不同。进程正常退出return退出
  在main函数中使用return退出进程是我们常用的方法。
  例如,在main函数最后使用return退出进程。
  运行结果:
  exit函数
  使用exit函数退出进程也是我们常用的方法,exit函数可以在代码中的任何地方退出进程,并且exit函数在退出进程前会做一系列工作:执行用户通过atexit或onexit定义的清理函数。关闭所有打开的流,所有的缓存数据均被写入。调用exit函数终止进程。
  例如,以下代码中exit终止进程前会将缓冲区当中的数据输出。
  运行结果:
  exit函数
  使用exit函数退出进程的方法我们并不经常使用,exit函数也可以在代码中的任何地方退出进程,但是exit函数会直接终止进程,并不会在退出进程前会做任何收尾工作。
  例如,以下代码中使用exit终止进程,则缓冲区当中的数据将不会被输出。
  运行结果:
  return、exit和exit之间的区别与联系
  return、exit和exit之间的区别
  只有在main函数当中的return才能起到退出进程的作用,子函数当中return不能退出进程,而exit函数和exit函数在代码中的任何地方使用都可以起到退出进程的作用。
  使用exit函数退出进程前,exit函数会执行用户定义的清理函数、冲刷缓冲,关闭流等操作,然后再终止进程,而exit函数会直接终止进程,不会做任何收尾工作。
  return、exit和exit之间的联系
  执行returnnum等同于执行exit(num),因为调用main函数运行结束后,会将main函数的返回值当做exit的参数来调用exit函数。
  使用exit函数退出进程前,exit函数会先执行用户定义的清理函数、冲刷缓冲,关闭流等操作,然后再调用exit函数终止进程。进程异常退出
  情况一:向进程发生信号导致进程异常退出。
  例如,在进程运行过程中向进程发生kill9信号使得进程异常退出,或是使用CtrlC使得进程异常退出等。
  情况二:代码错误导致进程运行时异常退出。
  例如,代码当中存在野指针问题使得进程运行时异常退出,或是出现除0的情况使得进程运行时异常退出等。三、进程等待进程等待的必要性子进程退出,父进程如果不读取子进程的退出信息,子进程就会变成僵尸进程,进而造成内存泄漏。进程一旦变成僵尸进程,那么就算是kill9命令也无法将其杀死,因为谁也无法杀死一个已经死去的进程。对于一个进程来说,最关心自己的就是其父进程,因为父进程需要知道自己派给子进程的任务完成的如何。父进程需要通过进程等待的方式,回收子进程资源,获取子进程的退出信息。获取子进程status
  下面进程等待所使用的两个函数wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统进行填充。
  如果对status参数传入NULL,表示不关心子进程的退出状态信息。否则,操作系统会通过该参数,将子进程的退出信息反馈给父进程。
  status是一个整型变量,但status不能简单的当作整型来看待,status的不同比特位所代表的信息不同,具体细节如下(只研究status低16比特位):
  在status的低16比特位当中,高8位表示进程的退出状态,即退出码。进程若是被信号所杀,则低7位表示终止信号,而第8位比特位是coredump标志。
  我们通过一系列位操作,就可以根据status得到进程的退出码和退出信号。exitCode(status8)0xFF;退出码exitSignalstatus0x7F;退出信号
  对于此,系统当中提供了两个宏来获取退出码和退出信号。WIFEXITED(status):用于查看进程是否是正常退出,本质是检查是否收到信号。WEXITSTATUS(status):用于获取进程的退出码。exitNormalWIFEXITED(status);是否正常退出exitCodeWEXITSTATUS(status);获取退出码
  需要注意的是,当一个进程非正常退出时,说明该进程是被信号所杀,那么该进程的退出码也就没有意义了。进程等待的方法wait方法
  函数原型:pidtwait(intstatus);
  作用:等待任意子进程。
  返回值:等待成功返回被等待进程的pid,等待失败返回1。
  参数:输出型参数,获取子进程的退出状态,不关心可设置为NULL。
  例如,创建子进程后,父进程可使用wait函数一直等待子进程,直到子进程退出后读取子进程的退出信息。includestdio。hincludestdlib。hincludeunistd。hincludesyswait。hincludesystypes。hintmain(){pidtidfork();if(id0){childintcount10;while(count){printf(Iamchild。。。PID:d,PPID:d,getpid(),getppid());sleep(1);}exit(0);}fatherintstatus0;pidtretwait(status);if(ret0){waitsuccessprintf(waitchildsuccess。。。);if(WIFEXITED(status)){exitnormalprintf(exitcode:d,WEXITSTATUS(status));}}sleep(3);return0;}
  我们可以使用以下监控脚本对进程进行实时监控:〔clVM015centosprocWait〕while:;dopsaxjhead1psaxjgrepprocgrepvgrep;echo;sleep1;done
  这时我们可以看到,当子进程退出后,父进程读取了子进程的退出信息,子进程也就不会变成僵尸进程了。
  waitpid方法
  函数原型:pidtwaitpid(pidtpid,intstatus,intoptions);
  作用:等待指定子进程或任意子进程。
  返回值:
  1、等待成功返回被等待进程的pid。
  2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0。
  3、如果调用中出错,则返回1,这时errno会被设置成相应的值以指示错误所在。
  参数:
  1、pid:待等待子进程的pid,若设置为1,则等待任意子进程。
  2、status:输出型参数,获取子进程的退出状态,不关心可设置为NULL。
  3、options:当设置为WNOHANG时,若等待的子进程没有结束,则waitpid函数直接返回0,不予以等待。若正常结束,则返回该子进程的pid。
  例如,创建子进程后,父进程可使用waitpid函数一直等待子进程(此时将waitpid的第三个参数设置为0),直到子进程退出后读取子进程的退出信息。includestdio。hincludestdlib。hincludeunistd。hincludesyswait。hincludesystypes。hintmain(){pidtidfork();if(id0){childintcount10;while(count){printf(Iamchild。。。PID:d,PPID:d,getpid(),getppid());sleep(1);}exit(0);}fatherintstatus0;pidtretwaitpid(id,status,0);if(ret0){waitsuccessprintf(waitchildsuccess。。。);if(WIFEXITED(status)){exitnormalprintf(exitcode:d,WEXITSTATUS(status));}else{signalkilledprintf(killedbysiganld,status0x7F);}}sleep(3);return0;}
  在父进程运行过程中,我们可以尝试使用kill9命令将子进程杀死,这时父进程也能等待子进程成功。
  注意:被信号杀死而退出的进程,其退出码将没有意义。多进程创建以及等待的代码模型
  上面演示的都是父进程创建以及等待一个子进程的例子,实际上我们还可以同时创建多个子进程,然后让父进程依次等待子进程退出,这叫做多进程创建以及等待的代码模型。
  例如,以下代码中同时创建了10个子进程,同时将子进程的pid放入到ids数组当中,并将这10个子进程退出时的退出码设置为该子进程pid在数组ids中的下标,之后父进程再使用waitpid函数指定等待这10个子进程。includestdio。hincludestdlib。hincludeunistd。hincludesystypes。hincludesyswait。hintmain(){pidtids〔10〕;for(inti0;i10;i){pidtidfork();if(id0){childprintf(childprocesscreatedsuccessfully。。。PID:d,getpid());sleep(3);exit(i);将子进程的退出码设置为该子进程PID在数组ids中的下标}fatherids〔i〕id;}for(inti0;i10;i){intstatus0;pidtretwaitpid(ids〔i〕,status,0);if(ret0){waitchildsuccessprintf(wiatchildsuccess。。PID:d,ids〔i〕);if(WIFEXITED(status)){exitnormalprintf(exitcode:d,WEXITSTATUS(status));}else{signalkilledprintf(killedbysignald,status0x7F);}}}return0;}
  运行代码,这时我们便可以看到父进程同时创建多个子进程,当子进程退出后,父进程再依次读取这些子进程的退出信息。
  基于非阻塞接口的轮询检测方案
  上述所给例子中,当子进程未退出时,父进程都在一直等待子进程退出,在等待期间,父进程不能做任何事情,这种等待叫做阻塞等待。
  实际上我们可以让父进程不要一直等待子进程退出,而是当子进程未退出时父进程可以做一些自己的事情,当子进程退出时再读取子进程的退出信息,即非阻塞等待。
  做法很简单,向waitpid函数的第三个参数potions传入WNOHANG,这样一来,等待的子进程若是没有结束,那么waitpid函数将直接返回0,不予以等待。而等待的子进程若是正常结束,则返回该子进程的pid。
  例如,父进程可以隔一段时间调用一次waitpid函数,若是等待的子进程尚未退出,则父进程可以先去做一些其他事,过一段时间再调用waitpid函数读取子进程的退出信息。includestdio。hincludestdlib。hincludeunistd。hincludesystypes。hincludesyswait。hintmain(){pidtidfork();if(id0){childintcount3;while(count){printf(childdosomething。。。PID:d,PPID:d,getpid(),getppid());sleep(3);}exit(0);}fatherwhile(1){intstatus0;pidtretwaitpid(id,status,WNOHANG);if(ret0){printf(waitchildsuccess。。。);printf(exitcode:d,WEXITSTATUS(status));break;}elseif(ret0){printf(fatherdootherthings。。。);sleep(1);}else{printf(waitpiderror。。。);break;}}return0;}
  运行结果就是,父进程每隔一段时间就去查看子进程是否退出,若未退出,则父进程先去忙自己的事情,过一段时间再来查看,直到子进程退出后读取子进程的退出信息。
  四、进程程序替换替换原理
  用fork创建子进程后,子进程执行的是和父进程相同的程序(但有可能执行不同的代码分支),若想让子进程执行另一个程序,往往需要调用一种exec函数。
  当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,并从新程序的启动例程开始执行。
  当进行进程程序替换时,有没有创建新的进程?
  进程程序替换之后,该进程对应的PCB、进程地址空间以及页表等数据结构都没有发生改变,只是进程在物理内存当中的数据和代码发生了改变,所以并没有创建新的进程,而且进程程序替换前后该进程的pid并没有改变。
  子进程进行进程程序替换后,会影响父进程的代码和数据吗?
  子进程刚被创建时,与父进程共享代码和数据,但当子进程需要进行进程程序替换时,也就意味着子进程需要对其数据和代码进行写入操作,这时便需要将父子进程共享的代码和数据进行写时拷贝,此后父子进程的代码和数据也就分离了,因此子进程进行程序替换后不会影响父进程的代码和数据。替换函数
  替换函数有六种以exec开头的函数,它们统称为exec函数:
  一、intexecl(constcharpath,constchararg,。。。);
  第一个参数是要执行程序的路径,第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾。
  例如,要执行的是ls程序。execl(usrbinls,ls,a,i,l,NULL);
  二、intexeclp(constcharfile,constchararg,。。。);
  第一个参数是要执行程序的名字,第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾。
  例如,要执行的是ls程序。execlp(ls,ls,a,i,l,NULL);
  三、intexecle(constcharpath,constchararg,。。。,charconstenvp〔〕);
  第一个参数是要执行程序的路径,第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾,第三个参数是你自己设置的环境变量。
  例如,你设置了MYVAL环境变量,在mycmd程序内部就可以使用该环境变量。charmyenvp〔〕{MYVAL2021,NULL};execle(。mycmd,mycmd,NULL,myenvp);
  四、intexecv(constcharpath,charconstargv〔〕);
  第一个参数是要执行程序的路径,第二个参数是一个指针数组,数组当中的内容表示你要如何执行这个程序,数组以NULL结尾。
  例如,要执行的是ls程序。charmyargv〔〕{ls,a,i,l,NULL};execv(usrbinls,myargv);
  五、intexecvp(constcharfile,charconstargv〔〕);
  第一个参数是要执行程序的名字,第二个参数是一个指针数组,数组当中的内容表示你要如何执行这个程序,数组以NULL结尾。
  例如,要执行的是ls程序。charmyargv〔〕{ls,a,i,l,NULL};execvp(ls,myargv);
  六、intexecve(constcharpath,charconstargv〔〕,charconstenvp〔〕);
  第一个参数是要执行程序的路径,第二个参数是一个指针数组,数组当中的内容表示你要如何执行这个程序,数组以NULL结尾,第三个参数是你自己设置的环境变量。
  例如,你设置了MYVAL环境变量,在mycmd程序内部就可以使用该环境变量。charmyargv〔〕{mycmd,NULL};charmyenvp〔〕{MYVAL2021,NULL};execve(。mycmd,myargv,myenvp);函数解释这些函数如果调用成功,则加载指定的程序并从启动代码开始执行,不再返回。如果调用出错,则返回1。
  也就是说,exec系列函数只要返回了,就意味着调用失败。命名理解
  这六个exec系列函数的函数名都以exec开头,其后缀的含义如下:l(list):表示参数采用列表的形式,一一列出。v(vector):表示参数采用数组的形式。p(path):表示能自动搜索环境变量PATH,进行程序查找。e(env):表示可以传入自己设置的环境变量。
  事实上,只有execve才是真正的系统调用,其它五个函数最终都是调用的execve,所以execve在man手册的第2节,而其它五个函数在man手册的第3节,也就是说其他五个函数实际上是对系统调用execve进行了封装,以满足不同用户的不同调用场景的。
  下图为exec系列函数族之间的关系:
  做一个简易的shell
  shell也就是命令行解释器,其运行原理就是:当有命令需要执行时,shell创建子进程,让子进程执行命令,而shell只需等待子进程退出即可。
  其实shell需要执行的逻辑非常简单,其只需循环执行以下步骤:获取命令行。解析命令行。创建子进程。替换子进程。等待子进程退出。
  其中,创建子进程使用fork函数,替换子进程使用exec系列函数,等待子进程使用wait或者waitpid函数。
  于是我们可以很容易实现一个简易的shell,代码如下:includestdio。hincludepwd。hincludestring。hincludeunistd。hincludestdlib。hincludesystypes。hincludesyswait。hdefineLEN1024命令最大长度defineNUM32命令拆分后的最大个数intmain(){charcmd〔LEN〕;存储命令charmyargv〔NUM〕;存储命令拆分后的结果charhostname〔32〕;主机名charpwd〔128〕;当前目录while(1){获取命令提示信息structpasswdpassgetpwuid(getuid());gethostname(hostname,sizeof(hostname)1);getcwd(pwd,sizeof(pwd)1);intlenstrlen(pwd);charppwdlen1;while(p!){p;}p;打印命令提示信息printf(〔sss〕,passpwname,hostname,p);读取命令fgets(cmd,LEN,stdin);cmd〔strlen(cmd)1〕;拆分命令myargv〔0〕strtok(cmd,);inti1;while(myargv〔i〕strtok(NULL,)){i;}pidtidfork();创建子进程执行命令if(id0){childexecvp(myargv〔0〕,myargv);child进行程序替换exit(1);替换失败的退出码设置为1}shellintstatus0;pidtretwaitpid(id,status,0);shell等待child退出if(ret0){printf(exitcode:d,WEXITSTATUS(status));打印child的退出码}}return0;}
  效果展示:
  说明:
  当执行。myshell命令后,便是我们自己实现的shell在进行命令行解释,我们自己实现的shell在子进程退出后都打印了子进程的退出码,我们可以根据这一点来区分我们当前使用的是Linux操作系统的shell还是我们自己实现的shell。

(卡塔尔世界杯)记者手记一个飞奔着去踢球的日本男孩新华社多哈11月23日电记者手记:一个飞奔着去踢球的日本男孩新华社记者王子江日本队在卡塔尔世界杯上逆转德国队,让我想起不久前在东京街头遇到的一个孩子,一个快乐如小鸟……Science今晨撤回天使粒子论文,张首晟等4人为通讯作者TOP大学来了小编按,11月18日凌晨3点,《科学》(Science)发布一则撤稿声明,撤回一篇发表于2017年7月21日的论文ChiralMajoranafermionmod……百公里电费只需6元?五菱NanoEV是否值得入手?这几年新能源微型车越来越受欢迎,不仅是因为其小巧可爱,容易穿梭在城市的大街小巷,而且后期的用车成本也较低,受到不少朋友的喜欢。今天我们就带大家看一款纯电微型车五菱NanoEV,……(卡塔尔世界杯观察)5换人规则改变世界杯新华社多哈11月25日电题:5换人规则改变世界杯新华社记者肖世尧、王浩宇、赵建通24日,卡塔尔世界杯首轮比赛结束,32支球队悉数亮相。从首轮比赛来看,本届赛事实行的……地球有多重?约6ronna克千字节、兆字节、吉字节更大的数据何以描述?毫米、微米、纳米多小的数字能穷尽微观世界?国际单位制日前引入4个新的用于构成十进倍数和分数单位的词头,分别扩展了最大和最小数字的计数单……中超最新积分榜武汉三镇重回第一,要夺队史第一个中超冠军了?山东泰山队1比2输成都蓉城,然后武汉三镇3比0胜成都蓉城,现在武汉三镇重新排名联赛第一,武汉三镇一定是冠军,山东泰山队接下来还是会掉链子,守门员这几场比赛肯定要继续出问题。中超……驻马店市6个村2个镇3个观光园区入选省级名单2022年河南省乡村旅游特色村、休闲观光园区、特色生态旅游示范镇等名单公布驻马店市6个村、2个镇、3个观光园区上榜驻马店网讯(记者刘金霞)近日,河南省文化和旅游厅公……愿每一个遭遇了感情背叛的人,都能伤愈归来(上)作者:艾闻(情感自媒体人)2015年,一次偶然的机缘,踏入情感自媒体领域,这一坚持就已经整整八年这些年来,见证了太多人的离合悲欢,感受了太多人的痛苦煎熬,当然,也陪……产8。74亿台,卖1。4亿台,国产手机怎么办?华为真我破局有苹果14上架前,很多网友大胆预测,苹果14将在苹果13的基础上继续涨价,从而拉开与苹果3的差价,不影响苹果13的销售,然而苹果14上架后,出乎众多分析师预料,苹果14不仅没涨价……构筑银行核心新引擎,长亮科技助力某城商行激发新动力近日,长亮科技助力某省级城商行核心系统与数据治理项目双重上线。历经13个月的负任蒙劳,通过建设稳定、高效、先进的核心业务系统新引擎,完美契合银行业务需求和技术要求,并充分体现以……人生苦短,别总是纠结过去《肖申克的救赎》里有一句话说得很好:人生就是一座监狱,监狱里面还有监狱,而最深的那个监狱则是你内心之中的绝望和沉沦。其实,人生不如意事十之八九,生活处处都充满绝望和……从钢铁厂到国家工业旅游示范基地福建三钢之变图为福建三钢工业旅游区。雷朝良摄中新网三明11月20日电(雷朝良)位于福建省三钢集团的1958工业记忆园内,一拨游客正在网红景点处打卡拍照。游人的休闲观光与厂内的繁忙景象……
已彻底无法登录!很多人还在等排队人数超千万退款路漫漫你的ofo,退押金了吗?不是DV君提醒大家是不是都忘了还有退押金这回事了?最近ofo小黄车退押金又有坏消息……内马尔受伤或遭清洗!巴黎求购28球18助锋霸,报价1亿和皇马大巴黎方面在买人建队这件事情上一直都是相当迷惑的,球队既然已经很明显的是中场和后防线有问题。但是大巴黎一直却对前锋线有着执着地补强想法,这前在冬窗就是想要求购曼联核心拉什福德,……杜兰特伤情比预期稍严重篮网考虑交易药罐子重建关键考验期来临NBA知名记者艾利克斯希弗最新报道,凯文杜兰特右膝内侧副韧带伤势与上赛季相似,这很可能导致篮网队进行重建,在休赛期交易无法保证健康的杜兰特进行重建。一年时间内,杜兰特第二……协同联动借势借力!河北涿州加快与北京一体化发展步伐河北新闻网讯(通讯员高长安)大兴机场涿州城市航站楼启用、京涿城际通勤高铁专列开通;央企入驻总数增长到58家、央企强市实践场景初具雏形;引入首都优质医疗资源、使百姓在家门口就能享……图养殖红掌的花期多长小技巧让花开的漂亮红掌的开花时间很长,只要掌握正确的养殖方法红掌基本上都是在开花的时期。但是在养殖的时候要掌握的技巧可是有很多知识的,小编下面分享下怎么养殖红掌吧!红掌在养殖的时候首先要选……这些祛湿误区千万别中招,小心越祛越湿经常感觉早上起床困难工作时犯困乏力时不时还会便秘这也有可能是湿气重发出的信号这些情况,说明你是湿性体质中医上,将湿性体质分为痰湿质、湿热质。……图怎么样养殖白凤多肉的习惯你了解吗白凤是多肉植物的一种,很多的人都喜欢养殖多肉植物。但是对于养殖的方法很多人掌握不好,就会遇到烂根、黄叶这些问题。小编下面分享下怎么养殖白凤吧!白凤是很好养殖的植物,只要掌……立春后,多吃以下几种蔬菜,味道比肉鲜导语:立春后,多吃以下几种蔬菜,味道比肉香。春天是万物生长的季节,春天主肝,也是肝火最旺盛的时候,肝脏最喜欢天然绿色食品,平常要多吃新鲜的蔬菜对身体有好处,青色的蔬菜有利……自然通讯聚合物纳米纤维网络组装制备坚固导电的水凝胶!导电水凝胶已应用于植入式生物电子学、组织工程平台、软致动器等新兴技术领域。然而,实现高导电性和机械稳健性仍然具有挑战性。近日,科研人员报告了一种基于聚合物纳米纤维网络的混合组装……图学习盆栽荷花方法任何空间都能成为荷塘荷花出淤泥而不染向来被人们誉为出水芙蓉,正因为如此很多爱花的朋友都希望可以在家里养殖它。可是荷花离开了池塘要怎么养殖呢?今天我们就来揭秘它的养殖方法。要把荷花养殖在盆里首……黄河上游出现大面积ampampquot流冰花ampampqu央广网西宁2月14日消息(记者贾海元)近日,随着气温回升,位于青海省果洛藏族自治州久治县境内的黄河河面结冰开始融化,融化后的冰块随着河水流动,形成奇特的流冰花景观。流冰花在两岸……图揭秘水培植物换水周期正确养殖让花更美丽水培植物观赏性强而且节省空间,可是很多养殖水培植物的朋友发现自己家里养殖的花总是看上去营养不良。其实这和换水的方法有分不开的关系,今天我们就来讲讲怎么给它换水。水培植物虽……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网