2022/3/3

进程是一个具有一定独立功能的程序的一次运行活动,同时也是资源分配的最小单元。

 

进程受系统内核管理,线程由进程创建和管理。

进程是放到磁盘的可执行文件,进程是指程序执行的实例。

进程是动态的,程序是静态的:进程不可复制移动,程序可以

进程是暂时的,程序是长久的:程序可以长期保存。

进程与程序组成不同:进程的组成包括程序,数据和进程控制块(即进程状态信息)

进程与程序的对应关系:通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。

进程的生命周期:创建,运行,撤销。每个进程由父进程创建,子进程也可以自己创建子进程。多个进程可以同时存在进程间可以通讯。进程可以被撤销,从而结束一个进程的运行。自己不可以清理进程表。

ps查看进程!查看后显示出来如下: pstree 进程以树的形状显示

pid=1;ppid=0;command=init 的进程(初始化进程)是所有用户进程的父进程。(他是用户进程的方式但是却有系统进程的身份。所有进程不能杀死他)。

撤销进程却没清理进程表中的进程号会产生僵尸进程,僵尸进程会占用进程表。

僵尸进程的产生:子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它父进程没有调用wait()或waitpid()函数来等待子进程的结束, 网络原因有时会引起僵尸进程;

僵尸进程的危害:僵尸进程会占用系统资源,如果很多,则会严重影响服务器的性能;

孤儿进程不会占用系统资源,最终是由init进程托管,由init进程来释放;

僵尸进程的处理:让僵尸进程成为孤儿进程,由init进程回收;(手动杀死父进程);调用fork()两次; 捕捉SIGCHLD信号,并在信号处理函数中调用wait函数;

任何一个进程都会经历僵尸进程阶段!父进程需要处理时间,这段时间撤销的时候就是僵尸进程

进程的状态:1.执行状态:进程正在占用CPU。2.就绪状态:不差条件只差CPU唤醒等待资源分配唤醒。3.等待状态:还差其他条件。

Linux系统是一个多进程的系统,具有并行性,互不干扰性。每个进程分配4G的虚拟空间。

进程ID:pid标识进程的唯一数字 

父进程的ID(PPID),启动进程的用户ID(UID)

进程互斥:是指若有若干进程都要使用某一共享资源的时候,任何时刻最多允许一个进程使用,其他要使用该资源的进程必须等待,直到占用该资源者释放了该资源为止。

临界资源:操作系统中将一次只允许一个进程访问的资源称为临界资源。可以共享但同时只能一个人访问。临界区:程序中的一段代码,应保证诸进程互斥地进入各自的临界区。

同步:按照一定的顺序执行的过程称为进程的同步。具有同步关系一组并发进程称为合作进程,合作进程间互相发送信号称为消息或事件。

进程的调度:按照一定的算法,从一组待运行的进程中,选出一个来占有CPU运行。

调度方式:抢占式和非抢占式。抢占式可以让别人剥夺CPU使用权。调度算法对非抢占式无效,因为非抢占不放出自己的CPU。

高级调度。中级调度。低级调度。

调度算法:可见此博主:

(10条消息) 常用的调度算法(包含实例)|操作系统_taoxing-CSDN博客_调度算法甘特图

死锁:两个进程僵住都不能往前推进。互相占用了对方的资源

获取ID:

#include <sys/types.h>

#include <unistd.h> pid_t getpid(void)     //获取本进程ID。

pid_t getppid(void)    //获取父进程ID
例:getpid.c (演示)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
   printf( "PID = %d\n", getpid() );
   printf( “PPID = %d\n”, getppid() );
   return 0;
}

创建进程:

#include<unistd.h>

pid_t fork(void)  功能:创建子进程,fork按照父进程的变量给子进程复制且分配空间。

#include <sys/types.h>
#include <unistd.h>
int main()
	{
		pid_t pid;
		/*此时仅有一个进程*/
		pid=fork();

              /*此时已经有两个进程在同时运行*/
		if(pid<0)
		printf("error in fork!");
		else if(pid==0)
		printf("I am the child process, ID is %d\n",getpid());
		else
		printf("I am the parent process,ID is %d\n",getpid());
}

fork的好处在于它被调用一次,却返回两次,它可能有三个不同的返回值,小于0失败,大于0返回父进程,返回0则是创建子进程。执行fork之前没有分配出子进程,后来才有的两个进程

 输出两个,fork创建子进程所以会有父进程则是两个进程,所以输出了两个。

在pid=fork()之前,只有一个进程在执行,但在这条语句执行之后,就变成两个进程在执行了,这两个进程的共享代码段,将要执行的下一条语句都是if(pid==0). 两个进程中,原来就存在的那个进程被称作“父进程”,新出现的那个进程被称作“子进程”,父子进程的区别在于进程标识符(PID)不同.

#include <unistd.h>
#include <stdio.h>
int main(void)
{
      pid_t pid;
	  int count=0;
      pid = fork();
	  count++;
	  printf( “count = %d\n", count );
	  return 0;
}

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
    pid_t pid;
    int count=0;
    pid=fork();
    if (pid <0)
    {
        printf("fail\n");

    }
    else if (pid==0)
    {
        count++;
        printf("child!%d\n",count);
    }
    else
    {
        count++;
        printf("parent!%d\n",count);
    }
    
    return 0;
    
}

 子进程的数据空间、堆栈空间都会从父进程得到一个拷贝,而不是共享。在子进程中对count进行加1的操作,并没有影响到父进程中的count值,父进程中的count值仍然为0

 vfork:创建的子进程不复制父进程的变量。但他可以直接用父进程的变量。子进程先执行后父进程执行。fork的执行顺序无所谓。

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void)
功能:创建子进程
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
    pid_t pid;
    int count=0;
    pid=vfork();
    if (pid <0)
    {
        printf("fail\n");

    }
    else if (pid==0)
    {
        count++;
        printf("child!%d\n",count);
    }
    else
    {
        count++;
        printf("parent!%d\n",count);
    }
    
    exit(0);
    
}

return 0;释放参数,子进程释放了父进程的count导致段错误。 改成exit(0);结束进程。

还可以改成在子进程中加入  _exit(0);   子进程释放。

vfork 和fork的区别:

1.   fork:子进程拷贝父进程的数据段       vfork:子进程与父进程共享数据段 2.   fork:父、子进程的执行次序不确定        vfork:子进程先运行,父进程后运行

 分析代码。

 exec 函数族:exec代码后的代码不执行.exec用被执行的程序替换调用它的程序。               

 区别:    fork创建一个新的进程,产生一个新的PID。exec启动一个新程序,替换原有的进程,因此进程的PID不会改变

#include<unistd.h>
int execl(const char * path,const char * arg1, ....)
参数:
path:被执行程序名(含完整路径)。
arg1 – argn: 被执行程序所需的命令行参数,含程序名。以空指针(NULL)结束。

如下:
 #include<unistd.h>
  int main()
 {
	execl(“/bin/ls”,”ls”,”-al”,”/etc/passwd”,NULL);
  }

#include<unistd.h>
int execv (const char * path, char * const argv[ ])
参数:
   path:被执行程序名(含完整路径)。
	argv[]: 被执行程序所需的命令行参数数组。

代码如下:
#include <unistd.h>
int main()
{
   char * argv[ ]={“ls”,”-al”,”/etc/passwd”,(char*)0};	execv(“/bin/ls”,argv);
}

 

 

#include <stdlib.h>
    		int system( const char* string )
功能:
   调用fork产生子进程,由子进程来调用/bin/sh -c string来执行参数string所代表的命令

#include <stdlib.h>
int main()
{
		system(“ls -al /etc/passwd”);
}

exec成功不返回,失败返回。exec只是执行新任务。exec后面的代码不会执行,system后面可以执行。

进程等待:

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait (int * status)

功能: 阻塞该进程,直到其某个子进程退出。

 

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{  pid_t pc,pr;
     pc = fork();
     if(pc == 0){
      printf(“This is child process with pid of %d\n”,getpid());
      sleep(10); /* 睡眠10秒钟 */
      }
      else if(pc > 0){
       pr=wait(NULL); /* 等待 */
       printf("I catched a child process with pid of %d\n"),pr);
       }
       exit(0);
}

另一种进程等待:

pid_t waitpid(pid_t pid, int *status,int options)

pid<-1 等待进程组识别码为pid 绝对值的任何子进程.
pid=-1 等待任何子进程, 相当于wait().
pid=0 等待进程组识别码与目前进程相同的任何子进程.
pid>0 等待任何子进程识别码为pid 的子进程.

参数option 可以为0也可以为WNOHANG:如果没有任何已经结束的子进程则马上返回, 不予以等待.

option =0时是阻塞等待,option =WNOHANG时是非阻塞等待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值