Linux常见进程控制与管理操作

目录

前言:

一、进程管理命令

1、在指定时间执行程序

2、进程的挂起与恢复命令

3、查看当前在线上的用户情况

4、显示当前登录的用户正在执行的命令

5、进程查看命令

6、指向的进程发送信号

二、进程管理(编程级别的)

1、fork()函数

2、wait()函数

3、exit()函数

4、kill()函数

5、signal()函数

6、pipe()函数

     编译运行环境:centOS

总结:


前言:

     不同的系统有不同的系统调用,相比于WindowsAPI中进线程的管理,我更喜欢Linux的进程管理(我才不会告诉你因为WindowsAPI代码对我来说太过繁重)。所以让我们来一起学习Linux进线程管理吧,首先对于Linux我们肯定是要了解进程管理命令的,然后才是我们的编程级别的进程创建与管理。


一、进程管理命令

1、在指定时间执行程序

命令格式:at time [day] [file]

说明:用户使用at命令在指定时刻执行指定的命令序列。

例如:10分钟后执行who命令(显示当前登录系统的用户)

$ at now +10min

at>who

at><EOT>(使用ctrl+D即可完成任务设定,会出现这个标志

2、进程的挂起与恢复命令

命令格式:bg/fg

说明:bg命令用来迫使被挂起的进程在后台运行。例如,当用户已经在前台启动了一个命令,但是它执行时间较长,而我们这个时候需要使用shell,那么我们可以ctrl+z把它挂起,然后bg命令放到后台执行,使用fg可以激活某个被挂起的进程并使它在前台运行。

例如

$ ./hello

Ctrl +Z

$ bg

或者唤醒

$ fg

3、查看当前在线上的用户情况

命令格式:who

说明:该命令主要用于查看线上的用户情况,系统管理员可以通过该命令监视每个登录用户的情况。

4、显示当前登录的用户正在执行的命令

命令格式:w

说明:w命令与who命令相比功能更加的强大,显示项目按照顺序排列:当前时间,系统启动到现在的时间,登录用户的数目,系统在最近1s、5s和15s的平均负载,最后是每个用户的各项数据,各项数据显示如下:登录账号、终端名称、远程主机名、登录时间、空闲时间、JCPU(和该终端连接的所有进程所占用的时间)、PCPU(当前进程所占用的时间)、当前正在运行进程的命令行。

例如

5、进程查看命令

命令格式:ps 【选项】

说明:改命令可以确定有哪些进程正在运行以及运行的状态、进程是否结束、哪些进程占用了过多的资源等。ps命令最常用的功能还是监控后台进程的工作情况。

选项含义

-e 显示所有进程

-f 全格式

-h 不显示标题

-l 长格式

-w 宽输出

-a 显示终端上的所有进程,包括其他用户的进程

-r 只显示正在运行的进程

-x 显示没有空格终端的进程

例如

以长格式查看属于自己的进程的详细信息

$ ps -l

6、指向的进程发送信号

命令格式:kill [-signal]进程号

说明:kill命令可以终止后台进程。kill命令时通过向进程发送指定的信号来结束进程的。如果没有发送指定信号,那么默认值为SIGTERM信号。SIGTERM信号将终止所有不能捕获该信号的进程。至于那些可以捕获该信号的进程可能就需要使用kill-9信号了,该信号是不能被捕获的。

选项含义

-signal 发送的信号类型,默认值为15,即SIGTERM信号,取值范围是1~30

例如,删除进程号(PID)为1330的进程:

$ kill 1330

若普通的无法删除,那么用:

$ kill -15 1330

如果连-15都无法删除,那么用:

$ kill -9 1330


二、进程管理(编程级别的)

     看完那么多炫酷的命令操作,在开始编程之前,让我们看看相关的函数。

1、fork()函数

fork()函数用于创建一个新进程(子进程)。其调用格式为:int fork();

返回值:

等于 0,表示当前进程时子进程,从子进程返回的ID值

大于 0, 表示当前进程时父进程,从父进程返回的子进程的进程ID值

等于-1,那么创建失败

2、wait()函数

 wait()函数用来控制父进程与子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。接到信号后,父进程提取子进程的终止状态字,从wait()函数返回,继续执行原程序。调用格式为:

#include<sys/type.h>

#include<sys/wait.h>

(pid_t) wait(int *statloc);

返回值:

大于0,为子进程的ID值

等于0,为其它

等于-1,表示调用失败

3、exit()函数

     exit()函数是进程结束最常用的函数,在main()函数中调用return,最终也是调用exit()函数(啊,C语言return 0白学了doge)。这些都是进程的正常终止。

调用格式为:

#include<stdio.h>

void exit(int status);

4、kill()函数

     kill()函数用于删除执行中的程序或者任务,调用格式为kill(int PID,int IID);

其中PID是要被杀死的进程号,IID为向将要被杀死的进程发送的中断号

5、signal()函数

signal()函数是允许调用进程控制软中断信号的处理。

格式为:

#include<signal.h>

int sig;

void(*func)();

signal(sig,function);

6、pipe()函数

pipe()函数用于创建一个管道,其调用格式为:

#include<unistd.h>

pipe(int fp[2]);

     那么让我们开始编程实现软中断通信吧,????你是不是有很多问好,什么是软中断,哈哈,其实就是模拟中断啦,让我们看看概念。

     中断(interrupt),是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理时间,使得CPU不得不暂停当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后再返回原来被中断处继续执行的过程。中断的发生一般而言是异步的,换句话说即使在无法预测的情况发生的(比如系统掉电)。所以计算机的软硬件对于中断的相应反应完全是被动的。

   软中断是对硬中断的一种模拟,发送软中断就是向接受程序的proc结构中的相应项发送一个特定意义的信号。软中断必须等到接收进程执行时才能生效。

     所以,我们只是模拟进程中创建、阻塞等情况呀,一起来编程吧!

     编译运行环境:centOS

#include<stdio.h>//exit()函数头文件
#include<signal.h>//signal()函数头文件
#include<unistd.h>//wait函数头文件
#include<sys/types.h>

int wait_flag;
void stop();//C语言函数原型声明,当然直接定义也可以,这里在末尾定义函数体
main() {
     int pid1,pid2;//定义两个进程号变量
     signal(3,stop);//sig==3为SIGQUIT退出
     while((pid1 = fork()) == -1);//若创建子进程1不成功,则空循环
     if(pid1>0) {
         while((pid2=fork())==-1);//若创建子进程2不成功,则空循环
         if(pid1>0) {
             wait_flag = 1;
             sleep(5);//父进程等待5s
             kill(pid1,16);//杀死子进程1
             kill(pid2,17);//杀死子进程2
             wait(0);//等待第一个子进程结束的信号
             wait(0);//等待第二个子进程结束的信号
             printf("\nParent process is killed!!\n");
            exit(0);//父进程结束
            }
         else {
             wait_flag = 1;
             signal(17,stop);//等待子进程2被杀死的中断号17
             printf("\nChild process 2 is killed by parent!!\n");
            exit(0);
             }
         }
     else{
         wait_flag = 1;
         signal(16,stop);//等待子进程1被杀死的中断号16
         printf("\nChild process 1 is killed by parent!!\n");
         exit(0);
         }
 }
 void stop(){
     wait_flag = 0;
 }
                                     

输出可能是:

Child process 1 is killed by parent!!

Child process 2 is killed by parent!!

Parent process is killed!!

或者:

Child process 2 is killed by parent!!

Child process 1 is killed by parent!!

Parent process is killed!!

     这个是因为从进程调度的角度来看,子进程被创建后处于就绪状态。此时,父进程和子进程作为两个独立的进程,共享一个代码段,分别参加调度、执行,直至进程结束。但是谁先谁后,和系统的调度策略和系统当前的资源状态有关,是不确定的。因为谁先从fork()函数中返回继续执行后面的语句也是不确定的。

     上面的wait、exit是很好理解的,但是signal可能就比较难理解。调用函数signal()都放在一段程序的前部,而不是在其他接收信号处。这是因为signal()执行只是起到为进程指定信号量16和17的作用,以及分配相应的与stop()过程链接的指针,从而signal()函数必须在程序的前部执行。其中sig的取值想要仔细了解可以找度娘查看。


总结:

     这篇博客简单的展示了Linux进程控制编程,要更深一步的了解,需要编写大量的实例,并去理解它们,关注我,一起学习呀,如有误,请指出,谢谢!

猜你喜欢

转载自blog.csdn.net/qq_43919400/article/details/106076898