Linux系统编程——进程(学习笔记)

一.使用的指令

        ps指令可以查看当前运行的进程

        ps -aux 和ps -ef 查看所有进程

        ps -aux|grep 进程类型   查看指定进程

        top指令可以观察cpu、内存使用情况

二.getpid函数

        函数原型pid_z getpid(void)

        获取当前进程的pid号(一般是该程序),返还一个非负整数

        每一个进程都一个非负整数表示唯一ID叫做PID,  

      pid_z pid;

        pid = getpid();

三.fork函数

        pid_t fork(void);——用于创建进程的函数

        fork函数返回两次返回值: 返回值为0时,代表当前进程为子进程;

                                                返回值为负数,代表当前进程为父进程;

                                                返回值为-1时,创建进程失败;

实例1:

在调用fork函数后,下面fork会返回两次并创建一个子进程

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


void main()
{
  pid_t pid;
  pid_t pid2;
 
  pid = getpid();
  printf("before fork pid is %d\n",pid);

  fork();

  pid2 = getpid();
  printf("pid2 = %d\n",getpid());

	  if(pid == pid2)
	 {
		 printf("This is father fork\n");
	 }else
	 {
		 printf("after fork pid is %d\n",getpid());
	 }

}

          使用fork创建的子进程会将父进程的代码变量等复制一份,在父子进程中对变量进行修改互相之间不影响,因为是复制的变量,不共用内存;

实例2:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


void main()
{
  pid_t pid;
  pid_t pid2;

  int a=10;
  int b=5;
 
  pid = fork();


	if(pid > 0)
	{
	 a = 50;
 	 printf("a = %d,b = %d pid = %d\n",a,b,getpid());
 	}
	if(pid == 0 )
 	{
	 b = 30;
 	 printf("a = %d,b = %d pid = %d\n",a,b,getpid());
	}

}

运行结果如上图:

使用fork的场景: 

实例3:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


void main()
{
  pid_t pid;
  int a;

   while(1)
  {
	printf("please input data\n");
	scanf("%d",&a);
	
	if(a == 1)
	{
		pid = fork();
		if(pid >0)
		{
			;
		}else if(pid == 0)
		{
			while(1)
			{
			
				printf("child fork %d\n",getpid());
				sleep(2);
			}
		}
	}else{
		printf("do nothing\n");
	}
  }
}

        通过父进程不断创建子进程.每当输入1就创建一个 子进程,各个进程一起运行。

 四.vfork函数

        pid_t vfork(void);也可以创建进程,

  vfork和fork的区别

  1. 区别一:vfork直接使用父进程存储空间,不拷贝。(在fork函数中创建的进程会复制一份父进程代码,所以在修改子进程时对父进程变量无影响,而在vfork创建的进程中,由于是共享的内存,对子进程中变量进行修改会影响这个变量在父进程中的值)

  2. 区别二:vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。(在fork中子进程和父进程的运行顺序有系统调度决定,在vfork创建的进程会先执行子进程等待子进程结束后父进程才执行,但需要子进程exit正常退出)

实例4: 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

void main()
{
  pid_t pid;
  pid_t pid2;
  int cnt = 0;
  int a = 10;
 
  pid = vfork();

	if(pid > 0)
	{
		while(1)
		{
 		  printf("this is father fork %d a = %d\n",pid,a);
		  sleep(2);
		}
 	}
	if(pid == 0 )
 	{
	
		while(1)
		{
		 printf("this is chlid fork %d\n",getpid());
		 sleep(2);
		 cnt++;
		 a = 20;
			if(cnt==3)
			{
				exit(1);
			}
		}
	}
}

运行结果如上图: (子进程运行次后退出进入父进程)

五.进程退出与等待

退出的类型

正常退出:

        1.Main函数调用return;

        2.进程调用exit(),标准c库;

        3.进程调用_exit()或者_Exit(),属于系统调用;

异常退出:

        1.调用abort;

        2.当进程收到某些信号时,如ctrl+C;

        3.最后一个线程对取消(cancellation)请求做出响应;

wait和waitpid函数

      pid_t wait(int *status)     

        在使用fork函数时,子进程与父进程的运行顺序是靠系统调度的,可以使用wait()函数对父进程进行阻塞 ; 

        当一个进程通过exit退出后需要对该进程的状态进行收集,可以使用wait函数进行收集exit(5)中的5,当不关心返回的状态码时 status可以为NULL;

        通过宏来解析收集到的结束码WEXITSTATUS(status) 打印结果为5;

WIFEXITED(status)   如果子进程正常结束,它就返回真;否则返回假。
WEXITSTATUS(status) 如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的结束代码。
WIFSIGNALED(status)如果子进程因为一个未捕获的信号而终止,它就返回真;否则返回假。
WTERMSIG(status)  如果WIFSIGNALED(status)为真,则可以用该宏获得导致子进程终止的信号代码。
WIFSTOPPED(status)  如果当前子进程被暂停了,则返回真;否则返回假。
WSTOPSIG(status)如果WIFSTOPPED(status)为真,则可以使用该宏获得导致子进程暂停的信号代码。
 

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

        pid<-1    等待进程组号为pid绝对值的任何子进程。
        pid=-1    等待任何子进程,此时的waitpid()函数就退化成了普通的wait()函数。
        pid=0    等待进程组号与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程。

        pid>0    等待进程号为pid的子进程。

   options参数为宏: 

wait和waitpid的区别

当使用wait函数时父进程会阻塞等待收集,而waitpid函数可以使用宏(WNOHANG)来避免阻塞;

实例5:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

void main()
{
  pid_t pid;
  pid_t pid2;

  int cnt = 0;
  int status = 0;
 
  pid = fork();

	if(pid > 0)
	{
	//	wait(&status);
		waitpid(pid,&status,WNOHANG);
		while(1)
		{
 		  printf("this is father fork %d status = %d\n",pid,WEXITSTATUS(status));
		  sleep(2);
		}
 	}
	if(pid == 0 )
 	{
	
		while(1)
		{
		 printf("this is chlid fork %d\n",getpid());
		 sleep(2);
		 cnt++;
			if(cnt==3)
			{
				exit(5);
			}
		}
	}
}

孤儿进程

        父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

     

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值