范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Linux系统进程管理

  (一)进程族系
  就如同人类的族系一样,系统中众多的进程也存在族系关系:由父进程创建子进程,子进程再创建子进程,从而构成一棵树形的进程族系图,如图2-9所示。图中结点代表进程。
  图2-9 进程创建的层次关系
  在开机时,首先引导操作系统,把它装入内存。之后生成第一个进程(在UNIX中称作0号进程),由它创建1号进程及其它核心进程;然后1号进程又为每个终端创建命令解释进程(shell进程);用户输入命令后又创建若干进程。这样便形成了一棵进程树。树的根结点(即第一个进程0#)是所有进程的祖先。上一层结点对应的进程是其直接相连的下一层结点对应进程的父进程,例如1#进程是P20,P21,P2n这些进程的父进程。
  (二)进程管理
  进程管理主要包括创建进程、终止进程、阻塞进程、唤醒进程和更换进程映像等。
  · 创建进程
  一个进程可以动态地创建新进程,前者称作 父进程 ,后者称作 子进程 。引发创建进程的事件通常是调度新的批作业、交互式用户登录、操作系统提供服务和现有进程派生新进程。
  创建新进程时要执行创建进程的系统调用(如UNIX/Linux系统中的fork),其主要操作过程有如下4步:
  (1)申请一个空闲的PCB。从系统的PCB表中找出一个空闲的PCB项,并指定惟一的进程标识号PID(即进程内部名)。
  (2)为新进程分配资源。根据调用者提供的所需内存的大小,为新进程分配必要的内存空间,存放其程序和数据及工作区。
  (3)将新进程的PCB初始化。根据调用者提供的参数,将新进程的PCB初始化。这些参数包括新进程名(外部标识符)、父进程标识符、处理机初始状态、进程优先级、本进程开始地址等。一般将新进程状态设置为就绪状态。
  (4)将新进程加到就绪队列中。一个进程派生新进程后,有两种可能的执行方式:
  ① 异步方式。即:父、子进程分道扬镳——父进程继续运行,子进程也可以被调度运行。
  ② 同步方式。即:父进程睡眠,等待它的某个或全部子进程终止,然后再继续运行。
  建立子进程的地址空间也有两种可能的方式:
  ① 子进程复制父进程的地址空间;
  ② 把新的程序装入子进程的地址空间。
  不同的操作系统采用不同的实现方式来创建进程。例如在UNIX系统中,每个进程有惟一的进程标识号(即PID),父进程利用fork系统调用创建新进程。父进程创建子进程时,把自己的地址空间制作一个副本,其中包括user结构、正文段、数据段、用户栈和系统栈。这种机制使得父进程很容易与子进程通信。两个进程都可以继续执行fork系统调用之后的指令,但有一个差别:fork的返回值(即子进程的PID)不等于0时,表示父进程在执行;而返回值等于0时,表示子进程在执行。Linux系统中也采用这种方式。
  · 终止进程
  当一个进程完成自己的任务后要终止自己,这是正常终止。如果进程在运行期间由于出现某些错误和故障而被迫终止,这是非正常终止。也可应外界的请求(如父进程请求)而终止进程。
  一旦系统中出现要求终止进程的事件后,便调用进程终止原语(原语是其操作不可分割的一段系统程序)。终止进程的主要操作过程是:
  (1)从系统的PCB表中找到指定进程的PCB。若它正处于运行态,则立即终止该进程的运行。
  (2)回收该进程所占用的全部资源。
  (3)若该进程还有子孙进程,则还要终止其所有子孙进程,回收它们所占用的全部资源。
  (4)释放被终止进程的PCB,并从原来队列中摘走。
  · 阻塞进程
  正在运行的进程因提出的服务请求未被操作系统立即满足,或者所需数据尚未到达等原因,只能转变为阻塞态,等待相应事件出现后再把它唤醒。
  正在运行的进程通过调用阻塞原语(如UNIX / Linux系统的sleep),主动地把自己阻塞。进程阻塞的过程如下:
  (1)立即停止当前进程的执行;
  (2)将现行进程的CPU现场送到该进程的PCB现场保护区中保存起来,以便将来重新运行时恢复此时的现场;
  (3)把该进程PCB中的现行状态由"运行"改为阻塞,把它插入到具有相同事件的阻塞队列中。
  (4)然后转到进程调度程序,重新从就绪队列中挑选一个合适进程投入运行。
  · 唤醒进程
  当阻塞进程所等待的事件出现时(如所需数据已到达,或者等待的I/O操作已经完成),则由另外的、与阻塞进程相关的进程(如完成I/O操作的进程)调用唤醒原语(如UNIX /Linux系统的wakeup),将等待该事件的进程唤醒。可见,阻塞进程不能唤醒自己。
  唤醒原语执行过程是:
  (1)首先把被阻塞进程从相应的阻塞队列中摘下;
  (2)将现行状态改为就绪态,然后把该进程插入到就绪队列中;
  (3)如果被唤醒进程比正在运行进程有更高的优先级,则设置重新调度标志。
  阻塞原语与唤醒原语恰好是一对相反的原语:调用前者是自己去睡眠,调用后者是把"别人"唤醒。使用时也要成对,前边有睡的,后边要有叫醒的。否则,前者就要"长眠"了。
  · 进程映像的更换
  子进程被创建之后,通常处于"就绪态"。以后,被进程调度程序选中才可以运行,即取得CPU的控制权。在有些系统(如UNIX/Linux)中,由于创建子进程时是把父进程的映像复制给子进程,所以父子进程的映像基本相同。如果子进程不改变自己的映像,就必然重复父进程的过程,这不是我们所要求的。为此,要改变子进程的映像,使它执行自己的特定程序。
  改变进程映像的工作很复杂,其主要过程是:
  (1)释放子进程原来的程序和数据所占用的内存空间;
  (2)从磁盘上找出子进程所要执行的程序和数据(通常以可执行文件的形式存放);
  (3)分配内存空间,装入新的程序和数据;
  (4)为子进程建立初始的运行环境——主要是对各个寄存器初始化,返回到用户态,运行该进程的程序。
  应当指出,以上几个进程管理原语是基本的功能性描述。在不同的操作系统中有不同的实现方式。
  (三)Linux进程管理
  1.Linux进程状态
  在Linux系统中,进程有下述5种状态:
  (1)运行态(TASK_RUNNING)。此时,进程正在运行(即系统的当前进程)或准备运行(即就绪态)。当前进程由运行指针所指向。
  (2)可中断等待态(TASK_INTERRUPTIBLE)。此时进程在"浅度"睡眠——等待一个事件的发生或某种系统资源,它能够被信号或中断唤醒。当所等待的资源得到满足时,它也被唤醒。
  (3)不可中断等待态(TASK_UNINTERRUPTIBLE)。进程处于"深度"睡眠的等待队列中,不能被信号或中断唤醒,只有所等待的资源得到满足时,才能被唤醒。
  (4)停止态(TASK_STOPPED)。通常由于接收一个信号,致使进程停止。正在被调试的进程可能处于停止态。
  (5)僵死态(TASK_ZOMBIE)。由于某些原因,进程被终止了,但是该进程的控制结构task_struct仍然保留着。
  如图2-10所示是Linux进程状态的变化。
  图2-10 Linux进程状态的变化
  2.进程的模式和类型
  在Linux系统中,进程的执行模式划分为用户模式(用户态)和内核模式(核心态)。如果当前运行的是用户程序、应用程序或者内核之外的系统程序,那么对应进程就在用户模式下运行;如果在用户程序执行过程中出现系统调用或者发生中断事件,就要运行操作系统(即核心)程序,进程模式就变成内核模式。在内核模式下运行的进程可以执行机器的特权指令,并且该进程不受用户的干预,即使是root用户也不能干预内核模式下进程的运行。
  按照进程的功能和运行的程序来分,进程划分为两大类:一类是系统进程,只运行在内核模式,执行操作系统代码,完成一些管理性的工作,如内存分配和进程切换。另一类是用户进程,通常在用户模式中执行,并通过系统调用或在出现中断、异常时进入内核模式。
  用户进程既可以在用户模式下运行,也可以在内核模式下运行,如图2-11所示。
  图2-11 用户进程的两种运行模式
  3.Linux进程结构
  · task_struct结构
  Linux系统中的每个进程都有一个名为task_struct的数据结构,它相当于"进程控制块"。系统中有一个进程向量数组task,该数组的长度默认值是512B,该数组的元素是指向task_struct结构的指针。在创建新进程时,Linux就从系统内存中分配一个task_struct结构,并把它的首地址 加入task数组。当前正在运行的进程的task_struct结构用current指针指示。
  task_struct结构包含下列信息:
  (1)进程状态。
  (2)调度信息。调度算法利用这个信息来决定系统中的哪一个进程需要执行。
  (3)标识符。系统中每个进程都有唯一的一个进程标识符(PID)。PID并不是指向进程向量的索引,仅仅是一个数字而已。每个进程还包括用户标识符(UID)和用户组标识符(GID),用来确定进程对系统中文件和设备的存取权限。
  (4)内部进程通信。Linux系统支持信号、管道、信号量等内部进程通信机制。
  (5)链接信息。在Linux系统中,每个进程都与其他进程存在联系。除初始化进程外,每个进程都有父进程。该链接信息包括指向父进程、兄弟进程和子进程的指针。
  (6)时间和计时器。内核要记录进程的创建时间和进程运行所用的CPU时间。Linux系统支持进程的时间间隔计时器。
  (7)文件系统。进程在运行时可以打开和关闭文件。task_struct结构中包括指向每个打开文件的文件描述符的指针,并且包括两个指向VFS(虚拟文件系统)索引节点的指针。第一个索引节点是进程的根目录,第二个节点是当前的工作目录。两个VFS索引节点都有一个计数字段,该计数字段记录访问该节点的进程数。
  (8)虚拟内存。大多数进程都使用虚拟内存空间。Linux系统必须了解如何将虚拟内存映射到系统的物理内存。
  (9)处理器信息。每个进程运行时都要使用处理器的寄存器及堆栈(参见下文关于堆栈的讲解)等资源。当一个进程挂起时,所有有关处理器的内容都要保存到进程的task_struct中。当进程恢复运行时,所有保存的内容再装回到处理器中。
  · 进程系统堆栈
  在Linux系统中,每个进程都有一个系统堆栈,用来保存中断现场信息和进程进入内核模式后执行子程序(函数)嵌套调用的返回现场信息。每个进程的系统堆栈和task_struct数据结构之间存在紧密联系,因而二者物理存储空间也连在一起,如图2-12所示。
  图2-12 进程的系统堆栈和task_struct结构
  由图2-12中可以看出,内核在为每个进程分配task_struct结构的内存空间时,实际上是一次分配两个连续的内存页面(共8KB),其底部约1KB的空间用于存放task_struct结构,而上面的约7KB的空间用于存放进程系统堆栈。
  另外,系统空间堆栈的大小是静态确定的,而用户空间堆栈可以在运行时动态扩展。
  (四)对进程的操作命令
  在Linux中,通常执行任何一个命令都会创建一个或多个进程,即命令是通过进程实现的。当进程完成了预期的目标,自行终止时,该命令也就执行完了。不但用户可以创建进程,系统程序也可以创建进程。可以说,一个运行着的操作系统就是由许许多多的进程组成的。
  1.ps命令
  ps命令是查看进程状态的最常用的命令,它可以提供关于进程的许多信息。操作者可以根据显示的信息确定哪个进程正在运行,哪个进程是被挂起或出了问题,进程已运行了多久,进程正在使用的资源情况,进程的相对优先级以及进程的标识号(PID)。所有这些信息对用户都很有用,对于系统管理员来说更为重要。
  ps命令的一般格式是:  ps [选项]
  例如,不带选项的ps命令可以列出每个与当前shell有关的进程的基本信息:
  $ ps
  PID
  TTY
  TIME
  CMD
  1788
  pts/1   00:00:00   bash   1822
  pts/1   00:00:00   ps   其中,各字段的含义如下:   PID 进程标识号。   TTY 该进程建立时所对应的终端,"?"表示该进程不占用终端。   TIME 报告进程累计使用的CPU时间。注意,尽管有些命令(如sh)已经运转了很长时间,但是它们真正使用CPU的时间往往很短。所以,该字段的值往往是00:00:00。   CMD 执行进程的命令名,command的缩写。   Ps命令的常用选项有:   -a 显示系统中与tty相关的(除会话组长之外)所有进程的信息。   -e 显示所有进程的信息。   -f 显示进程的所有信息。   -l 以长格式显示进程信息。   -r 只显示正在运行的进程。   -u 显示面向用户的格式(包括用户名,CPU及内存使用情况、进程运行状态等信息)。   -x 显示所有终端上的进程信息。 例如,下面的命令行可以显示系统中所有进程的全面信息:   $ ps -ef   UID   PID   PPID   C   STIME   TTY   TIME   CMD   root   1
  0
  1
  20:42   ?   00:00:05   init [5]   root   2
  1
  0
  20:42   ?   00:00:00   [keventd]   root   3
  1
  0
  20:42   ?   00:00:00   [ksoftirqd_CPU0]   ……   mengqc   1823
  1788
  0
  21:39   pts/1   00:00:00   ps -ef   各项的含义是(只标出与前例不同的部分,其余含义相同):   UID 进程属主的用户ID号。   PPID 父进程的ID号。   C 进程最近使用CPU的估算。   STIME 进程开始时间,以"小时:分:秒"的形式给出。   2.kill命令   信号(signal,也称作软中断)机制是在软件层次上对中断机制的一种模拟。异步进程可以通过彼此发送信号来实现简单通信。系统预先规定若干个不同类型的信号(如x86平台中Linux内核设置了32种信号,而现在的Linux和POSIX.4定义了64种信号),各表示发生了不同的事件,每个信号对应一个编号。进程遇到相应事件或者出现特定要求时(如进程终止或运行中出现某些错误——非法指令和地址越界等),就把一个信号写到相应进程task_struct结构的signal位图(表示信号的整数)中。接收信号的进程在运行过程中要检测自身是否收到了信号,如果已收到信号,则转去执行预先规定好的信号处理程序。在处理之后,再返回原先正在执行的进程。   kill命令是通过向指定进程发送指定的信号来终止相应进程。终止一个前台进程可以使用键,也可以使用kill命令。但是,对于一个后台进程就只能用kill命令来终止。   kill命令的一般格式是:   kill [-s 信号|-p ] 进程号…   kill -l [信号]   其中,各选项的含义如下:   -s 指定要发送的信号——可以是信号名(如SIGKILL),也可以是对应信号的编号(如9)。   -p 指定kill命令只是显示进程的PID(进程标识号),并不真正发出终止进程的信号。   -l 显示信号名称列表,这也可以在/usr/include/linux/signal.h文件中找到。   使用kill命令时应注意:   (1)kill命令可以带信号,也可以不带。如果没有带信号,kill命令就会发出终止信号(编号为15),这个信号可以被进程捕获,使得进程在退出之前清理并释放资源。也可以用kill向进程发送特定的信号,例如:kill -2 123 。它的效果等同于:当在前台运行PID为123的进程时,按下键。但是,普通用户使用kill命令时不要带信号,或者至多带信号编号9。   (2)kill可以用进程ID号作为参数。当用kill向这些进程发送信号时,必须是这些进程的主人。如果试图撤销一个没有权限撤销的进程或撤销一个不存在的进程,就会得到一个错误信息。   (3)可以向多个进程发信号或终止它们。   (4)当kill成功地发送了信号后,shell会在屏幕上显示出进程的终止信息。有时这个信息不会马上显示,只有当按下键使shell的命令提示符再次出现时,才会显示出来。   (5)应注意,信号使进程强行终止,这常会带来一些副作用,如数据丢失或者终端无法恢复到正常状态。发送信号时必须小心,只有在万不得已时,才用SIGKILL信号(编号为9),因为进程不能首先捕获它。   要撤销所有的后台作业,可以输入kill 0。因为有些在后台运行的命令会启动多个进程,跟踪并找到所有要杀掉的进程的PID是件很麻烦的事。这时,使用kill 0 来终止所有由当前shell启动的进程,是个有效的方法。   一般可以用kill命令来终止一个已经挂起的进程或者一个陷入死循环的进程。例如:首先执行以下命令,人为建立一个好像陷入死循环的后台进程:   $ find / -name core -print > /dev/null 2>&1&   这是一条后台命令,执行时间较长。其功能是:从根目录开始搜索名为core的文件,将结果输出(包括错误输出)都定向到 /dev/null文件。   现在决定终止该进程。为此,运行ps命令来查看该进程对应的PID。例如,该进程对应的PID是1651,现在用kill命令"杀死"这个进程:   $ kill 1651   再用ps命令查看进程状态时,就可以看到,find进程已经不存在了。   3.sleep命令   sleep命令的功能是使进程暂停执行一段时间。其一般使用格式是:   sleep 时间值   其中,"时间值"参数以秒为单位,即让进程暂停由时间值所指定的秒数。此命令大多用于shell程序设计中,使两条命令执行之间停顿指定的时间。   例如,下面的命令使进程先暂停100秒,然后查看用户mengqc是否在系统中:   $ sleep 100; who | grep "mengqc"   (五)有关进程控制的系统调用   1.系统调用的使用方式   虽然在一般应用程序的编制过程中,利用系统提供的库函数就能很好地解决问题,但在处理系统底层开发、进程管理等方面的涉及系统内部操作的问题时,利用系统调用编程就很必要,而且程序执行的效率会得到改进。   在UNIX/Linux系统中,系统调用和库函数都是以C函数的形式提供给用户的,它有类型、名称和参数,并且要标明相应的文件包含。例如,open系统调用可以打开一个指定文件,其函数原型说明如下:   #include   #include   #include   int open(const char *path, int oflags);   不同的系统调用所需要的头文件(又称前导文件)是不同的。这些头文件中包含了相应程序代码中用到的宏定义、类型定义、全称变量及函数说明等。对C语言来说,这些头文件几乎总是保存在/usr/include及其子目录中。系统调用依赖于所运行的UNIX/Linux操作系统的特定版本,所用到的头文件一般放在/usr/include/sys或者 /usr/include/linux目录中。   在C语言程序中,对系统调用的调用方式与调用库函数的方式相同,即:调用时提供的实参的个数、出现的顺序和实参的类型应与原型说明中形参表的设计相同。例如,要打开在目录/home/mengqc下面的普通文件myfile1,访问该文件的模式为可读可写(用符号常量O_RDWR表示),则代码片段为:   int fd;   …   fd=open("/home/mengqc/myfile1",O_RDWR);   …   虽然从感觉上系统调用类似于库函数调用:都由程序代码构成,使用方式相同——调用时传送参数。但两者有实质差别:库函数属于用户层,它只能在用户态下运行,不能进入核心态;而系统调用属于操作系统核心层,在核心态下运行,并且可以实现处理机从用户态到核心态的转变。   2.有关进程控制的系统调用   常用的有关进程控制的系统调用有:fork,exec,wait,exit,getpid,sleep和nice等。查看表2-1列出了这些系统调用的格式和功能说明 。   表2-1 有关进程控制的系统调用的格式和功能说明   格式   功能   #include   #include   pid_t fork(void);   创建一个子进程。pid_t表示有符号整型量。若执行成功,在父进程中,返回子进程的PID(进程标识符,为正值);在子进程中,返回0。若出错,则返回 1,且没有创建子进程   #include   #include   pid_t getpid(void);   pid_t getppid(void);   getpid返回当前进程的PID,而getppid返回父进程的PID   #include   int execve(const char *path,char *const argv[],char *const envp[]);   int execl(const char *path, const char *arg,...);   int execlp(const char *file, const char *arg,...);   int execle(const char *path, const char *arg,...,char *const envp[]);   int execv(const char *path, char *const argv[]);   int execvp(const char *file, char *const argv[]);   这些函数被称为"exec函数系列",其实并不存在名为exec的函数。只有execve是真正意义上的系统调用,其他都是在此基础上经过包装的库函数。该函数系列的作用是更换进程映像,即根据指定的文件名找到可执行文件,并用它来取代调用进程的内容。换句话说,即在调用进程内部执行一个可执行文件。其中,参数path是被执行程序的完整路径名;argv和envp分别是传给被执行程序的命令行参数和环境变量;file可以简单到仅仅是一个文件名,由相应函数自动到环境变量PATH给定的目录中去寻找;arg表示argv数组中的单个元素,即命令行中的单个参数   #include   void _exit(int status);   #include   void exit(int status);   终止调用的程序(用于程序运行出错)。参数status表示进程退出状态(又称退出值、返回码、返回值等),它传递给系统,用于父进程恢复。_exit函数比exit函数简单些,前者使得进程立即终止;后者在进程退出之前,要检查文件的打开情况,执行清理I/O缓冲的工作   #include   #include   pid_t wait(int *status);   pid_t waitpid(pid_t pid, int *status,int option);wait( )等待任何要僵死的子进程;有关子进程退出时的一些状态保存在参数status中。如成功,返回该终止进程的PID;否则,返回1   而waitpid( )等待由参数pid指定的子进程退出。参数option规定了该调用的行为:WNOHANG表示如没有子进程退出,则立即返回0;WUNTRACED表示返回一个已经停止但尚未退出的子进程的信息。可以对它们执行逻辑"或"   #include   unsigned int sleep(unsigned int seconds);   使进程挂起指定的时间,直至指定时间(由seconds表示)用完或者收到信号   #include   int nice(int inc);   改变进程的优先级。普通用户调用nice时,只能增加进程的优先数(inc为正值);只有超级用户才能减少进程的优先数(inc为负数)。如成功,返回0;否则,返回1   3.应用示例   【例2-1】子进程被创建后,一般会使用一个exec函数来更换自己的映像,即用一个程序(如可执行文件)取代原来内存空间中的内容,然后开始执行。此后,父、子进程就各行其道了。父进程可以创建多个子进程。当子进程运行时,如果父进程无事可做,就执行wait系统调用,把自己插入睡眠队列中,等待子进程的终止。   下面这个C程序展示了Linux系统中父进程创建子进程以及各自分开活动的情况。   【例2-2】每个进程都有唯一的进程ID号(PID)。PID通常在数值上逐渐增大,因此,子进程的PID一般要比其父进程大。当然,PID的值不可能无限大,当它超过系统规定的最大值时,就反转回来使用最小的尚未使用的PID值。   如图2-9所示,进程族系呈树型结构。除0#外,任何进程都必须有父进程,不允许出现"孤儿"进程。如果父进程先于子进程死亡或退出,则子进程会被指定一个新的父进程init(其PID为1)。   下面的程序利用fork( )创建子进程,利用getpid( )和getppid( )分别获得本进程的PID和父进程的PID,使用sleep( )将相关进程挂起几秒钟。本程序的可执行文件名为proc1。   /*proc1.c演示有关进程操作*/   #include   #include   #include   #include   int main(int argc,char **argv)   {   pid_t pid,old_ppid,new_ppid;   pid_t child,parent;   parent=getpid(); /*获得本进程的PID*/   if((child=fork())<0){ /*如果新创建子进程的PID小于0*/   fprintf(stderr,"%s:fork of child failed:%s ",argv[0],strerror(errno)); /*输出创建子进程失败*/   exit(1); /*终止,返回码为1*/   }   else if(child==0){ /*此时是子进程被调度运行*/   old_ppid=getppid(); /*取得父进程的PID*/   sleep(2); /*睡眠2秒钟,以便调度其他进程运行*/   new_ppid=getppid(); /*当再次被调度运行后,取得新父进程的PID*/   }   else { /*父进程运行*/   sleep(1); /*睡眠1秒钟,以便调度其他进程运行*/   exit(0); /*被调度运行时,父进程终止*/   }   /*下面仅子进程运行*/   printf("Original parent:%d ",parent); /*输出最初父进程的PID*/   printf("Child:%d ",getpid()); /*取得并输出子进程的PID*/   printf("Child"s old ppid:%d ",old_ppid); /*输出父进程的PID*/   printf("Child"s new ppid:%d ",new_ppid); /*输出新父进程的PID*/   exit(0); /*程序终止*/   }   程序运行的结果如下:   $ ./proc1   $ Original parent:2009   Child:2010   Child"s old ppid:2009   Child"s new ppid:1   请读者根据输出结果自行分析程序的执行情况。注意,进程是并发执行的;当子进程被成功调度后,调度程序的返回值是0。如果父进程先终止,则其子进程的父进程就被系统指定为init进程(其PID为1)。

国产巨头更换新售后规则,只为接力华为,压力来到iPhone这现在的消费者换手机比起曾经会纠结很多,主要还是现在的手机功能和新技术太多,加上还有不同的售后规则,让人不知道如何选择。而衡量一家手机品牌是否良心的标准有很多,除了产品质量外,售后是简单易用的高性价比循环泵戴博屏蔽式循环泵VA系列评测水泵好像离我们的生活很遥远,两三年之前,我也没有意识到水泵对于日常家居有多重要,但是在近几年构建智能家居和家庭水系统的时候,逐渐发现水泵原来是生活中不能缺少的部分。其实我们已经用到iPhone浏览器Safari的8个技巧,一定要学会用了5年的Safari浏览器,今天给大家总结了8个Safari浏览器的使用技巧,帮你彻底发挥苹果内置浏览器的全部能力。一共是下面这八类,大家可以结合文字和图片说明进行操作无广告看小实测倍轻松Neck5颈部按摩器带来的真大师级按摩体验当代职场人的颈椎,已经快不行了。上班长时间盯着电脑低着头,一坐就是一整天,好不容易遇到周末,也宅家懒运动,低头盯着手机刷不停。日积月累,不只眼睛遭罪,脖子更是难受。颈椎也是苦不堪言同事刚到手的iPhone14ProMax,用iPhone12的朋友体验完说了仨感受现在想在第一时间拿到iPhone14ProMax,真不是一件容易的事儿。所以,我同事一个月前付完了钱,目前才拿到iPhone14ProMax真机。不过,说心里话同事刚拿到iPhon华为PocketS折叠屏翻车,绿屏问题可能是撕掉了偏光片最近很多华为PocketS折叠屏的用户曝光出屏幕质量问题,折痕太严重了,屏幕发绿光的问题!让我很奇怪的是某东某宝还有华为商城评论全部都关闭了,这是什么操作呢?华为为啥不好好解决问题2002年华为到底经历了什么?任正非每天在做噩梦,梦醒时常常哭?2002年,在深圳华为基地,近6000名新员工,正等待着任正非的一个解释,明明是让我来做研发,凭什么现在要去当维修工!更有甚者,直接冲上讲台,对着任正非吼你一口气招这么多人,是不是互联网如何获得用户信任?过剩年代的的机会在哪里?有个问题思考一下,其实你是喜欢选择多的,还是喜欢选择少的?我们很多商家认为给顾客提供的选择越多,顾客越开心,其实是不对的。在今天做平台营销的人,是不是真正了解到顾客心理呢?有位外国年度最火刘海,来了由于两部新剧同时播出,最近,杨幂在屏幕里的曝光又大大增加了。除了粉丝们在认真追剧,还有一拨网友瞄上了她的毛绒绒的长出旺盛小碎发的发际线。有人猜测,这是植发后新长出来的头发还有人已经早安日历每日一签12072022年12月07日,星期三,农历冬月十四,今天是二十四节气大雪。飘雪带来寒冬,但梦想仍有温度。大雪天寒,但总有人愿意借你阳光。雪落方知冬意万物至此臻藏已讶衾枕冷,复见窗户明夜深说一说我心中的孙少平文释贤桓2022。12。6人不能苦一辈子!大一那年,宿舍里住着一位来自榆林定边的同学,我俩关系很好,他床头经年放着一踏发黄带着卷边的书,暑假里大家都回家了,我一边打工一边住宿舍,闲
生物学上首次科学家发现有两套DNA的动物IT之家4月10日消息,黄疯蚁(Anoplolepisgracilipes)又称长足捷蚁或马尔代夫蚁,最早在非洲被发现,随着人类的商业货物活动向全球扩散,成为一种危险的入侵生物。由4月9日医讯早报白内障不是专盯老年人,出现这些症状需当心1人工智能医疗器械推动诊疗流程向标准化方向发展今年2月,人工智能医疗器械产业发展白皮书发布。白皮书提出,人工智能医疗器械推动诊疗流程向标准化方向发展。医学中的诊断治疗高度依赖医生个什么是骨质疏松症?如何预防和治疗?骨质疏松症是一种骨骼疾病,其特征是骨密度降低和骨的微结构退化,导致骨头变得脆弱和易碎。这种疾病常常被称为脆骨症,因为它使得骨头容易发生骨折。这种疾病通常在中老年人中更为常见,尤其是人活到70岁就行,不需要太长寿,长寿的因素都有哪些?人活到70岁,已经算长寿了。寿命长,有一个很重要的意义让人体会到生命的可贵,珍惜生命,享受生活。人活到70岁,身体机能可能已经出现衰退。对于老年人来说,过了70岁,身体就在走下坡路增加排尿量能降低尿酸高,这个中药增加排尿量,还能攻克痛风炎症我们知道,痛风的发生是因为尿酸高,尿酸高很大的因素是因为排泄障碍,这种时候增加排尿量就非常重要,那么有没有增加排尿量的中成药呢?老陈可以很负责的告诉你有,临床上比较常见的就是防己,必看一年8亿只!没有一只鸡可以活着离开广东鸡有鸡味是广东人对一只鸡的最高赞赏!无论是逢年过节还是平常聚餐广东人的餐桌上都少不了一只鸡据国家农业科创中心数据显示广东人一年就能干掉8亿只鸡据2022广东统计年鉴,2021年,广不论炖什么肉,切记要加这2种料!保证肉烂而有嚼口,鲜香,入味导读不论炖什么肉,切记要加这2种料!保证肉烂而有嚼口,鲜香,越炖越入味!春天已经到来,白天温度高,夜晚寒冷,是流感的高发季节,在这时期,我们就需要多吃肉类食物,通过补充蛋白质从而提新民快评兰州牛肉面正名,期待更好服务民众生活首先,考你一个问题知道兰州拉面和兰州牛肉面的区别吗?遍布大街小巷的兰州拉面,虽然被冠以兰州拉面的头衔,但它真正的出身却是青海省海东市化隆县。上世纪八十年代,化隆人走出大山,开始把拉睡得浅睡得短睡不安稳?两味药泡水,养心宁神,助你深睡晚上不睡,第二天崩溃!睡不好觉有多痛苦,想必很多人一定都深有体会。睡眠浅,睡的时间短,睡得不安稳老是醒那像这些睡眠问题,难道只能借助安眠药来调理吗?那当然不是了!今天贾医生就来教你乌拉圭对华出口牛肉所缴纳的关税占其全部牛肉出口关税的59商务部发布,据乌拉圭国家报3月28日报道,乌肉类协会报告称,2022年牛肉出口额超26亿美元,关税负担达3。16亿美元,比前一年增长了1000万美元。中国仍然是乌牛肉缴纳关税最多的刚刚封板就筹划下个雪季吉林持续聚焦冰雪经济新动能这几天,随着气温转暖,位于吉林的北大湖等滑雪度假区陆续封板。记者在北大湖滑雪场看到,新项目建设场地上一派忙碌景象,工程机械轰鸣,工人们干劲十足。北京冬奥会后的首个雪季刚刚结束,吉林