linux进程

linux进程

进程:头文件#include<unistd.h>

程序:是存在在外部介质上的可执行文件

进程:是程序执行的具体实例(过程)

ps:进程状态是不断变化的

进程的状态:

1.就绪态:一切准备的。

2.执行态:占用cpu开始执行。

3.等待态:由于进程不符合某些条件,等待执行。ps:scanf

进程的调度:以上三种状态来回切换

进程的控制:一个程序可以有多种进程,程序多开

进程号:(唯一的)(可以重复使用)0-32767(最多跑32767个程序,单片机进程范围)

ps进程号为0 、 1的进程我们无法使用

进程号0:调度进程 进程号1:初始化进程

进程的开始必须由进程创建,都是由初始化进程开始

父进程号:创建你这个进程的名字

进程组号:多个相关联的进程

getpid();查看进程号

创建一个进程号:fork函数:有两个返回值

作用:创建一个子进程,两个进程为竞争关系(竞争上岗)

fork():调用fork时,下面的代码会分裂复制

创建进程

1、每个进程都由父进程创建。

2、通过系统调用函数 fork() 实现进程创建。

fork()

1、头文件:<sys/types.h> <unistd.h>

2、函数原型:pid_t fork();

3、返回值:PID,进程ID号。返回 0 表示子进程,返回-1失败,返回大于0的整数表示创建进程的PID。

4、可以通过getpid()来获取当前运行的进程ID,通过getppid()获取当前进程的父进程ID。

5、fork函数的子进程会复制父进程的所有内存空间(五大分区:静态全局区,堆,栈,文字常量区,代码段)

getpid():当前进程号

getppid:父进程号

__getpgid(gitpid()):组进程:()里面要加一个组成员

进程相关命令

查看进程

ps aux / ajx

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

u:显示进程的详细信息

x:显示没有控制终端的进程

j:列出与作用控制先关的信息

杀死进程

kill [-signall] pid
kill -l 列出所有信号
kill -SIGKILI  进程ID
killall name 根据进程杀死进程

特殊的几种进程:

1、僵尸进程:进程已结束,但是进程的资源没有被回收(内存泄漏)

2、孤儿进程:子进程未结束,父进程就已经结束,子进程资源无人回收。

ps:孤儿进程会转化为僵尸进程,很危险

3、守护进程:特殊的孤儿进程,不会停止进程,用来回收孤儿进程、僵尸进程,保护进程,运行在后台

sleep(time):让进程挂起time秒,等待态(进程的挂起状态)

进程的等待:为避免子进程成为孤儿,让父进程进入等待态,等待函数:wait():父进程等待子进程结束,子进程结束后回收子进程的内存。

WIFEXITED:判断进程是否正常退出,非空即为正常退出

WEXITSTATUS:将高八位后移八位

进程的终止

exit:库函数 <stdlib.h> :调用退出处理函数.

_exit:系统调用,<unistd.h>

atexit:(Func函数):在程序结束前调用并释放所有内存

vfork:创建一个子进程:保证子进程先动,只有在出现exec(执行别的程序)或者exit(结束当前程序)函数之后才会执行父进程

ps:vfork的子进程是在父进程的地址空间中进行的,所以会对父进程的数据有影响

exec函数族

功能:在一个进程中启动另外的程序

  1. execl()

    • 功能:替换当前进程映像,参数以NULL终止的列表形式给出。
    • 原型:pid_t execl(const char *path, const char *arg, ... /* (char *)NULL */);
    • 参数:path是要执行的程序路径,arg是程序的第一个参数,之后的参数以NULL终止。
  2. execv()

    • 功能:与execl类似,但参数列表是一个字符串数组。
    • 原型:pid_t execv(const char *path, char *const argv[]);
    • 参数:path是要执行的程序路径,argv是一个字符串数组,其中argv[0]是程序名,argv[n]是参数,argv[n+1]是NULL。
  3. execle()

    • 功能:与execl相似,但允许额外的环境变量列表。
    • 原型:pid_t execle(const char *path, const char *arg, ... /* (char *)NULL */, char *const envp[]);
    • 参数:pathargexecl相同,envp是一个字符串数组,用于指定额外的环境变量。
  4. execve()

    • 功能:与execv相似,但允许额外的环境变量列表。
    • 原型:pid_t execve(const char *path, char *const argv[], char *const envp[]);
    • 参数:pathexecv相同,argv是参数数组,envp是环境变量数组。
  5. execlp()execvp()

    • 功能:这两个函数与execlexecv类似,但它们会在环境变量PATH中搜索程序路径。
    • 原型:pid_t execlp(const char *file, const char *arg, ... /* (char *)NULL */);pid_t execvp(const char *file, char *const argv[]);

所有这些函数在成功执行新程序时都不返回,如果执行失败,则返回-1,并通过errno全局变量提供错误信息。

使用exec函数族时,通常会与fork函数配合使用,先创建子进程,然后在子进程中调用exec函数来执行新程序。这样做的原因是exec会替换当前进程的执行上下文,如果你想保留父进程的执行流,就需要在子进程中调用exec

perror():读取出了什么问题 ps:perror(“函数名”)

system函数:开启一个子进程,运行传入的字符串命令行

IPC(进程间通信)

指的是在计算机系统中,不同进程之间交换数据或同步操作的方法。由于每个进程都有自己的独立地址空间,因此它

们不能直接访问彼此的数据。IPC机制允许进程间进行协作和数据交换,这对于分布式计算、多任务操作系统和网络服务都是至关重要的

在Unix和类Unix系统中,常见的IPC机制包括:

  1. 管道(Pipes)
    • 无名管道(Anonymous Pipes):只用于具有亲缘关系的进程(如父子进程)之间的通信,是半双工的,数据只能单向流动。
    • 命名管道(Named Pipes 或 FIFOs):类似于无名管道,但存在于文件系统中,可以被任意进程打开和使用,提供了一种进程间异步通信的方式。
  2. 消息队列(Message Queues)
    • 提供了在进程间传递消息的能力,消息队列中的消息有长度限制,每个消息包含一个类型字段,允许进程根据类型过滤消息。
  3. 信号量(Semaphores)
    • 用于控制多个进程对共享资源的访问,提供了一种防止竞态条件的机制,可以实现进程间的互斥和同步。
  4. 共享内存(Shared Memory)
    • 允许多个进程访问同一块内存区域,是最快的IPC机制之一,因为数据不需要在进程间复制,但是需要额外的同步机制(如信号量)来防止并发访问问题。
  5. 套接字(Sockets)
    • 主要用于网络通信,但也可用于同一台机器上的进程间通信,提供了可靠的流式或数据报式通信,支持TCP/IP和UDP协议。
  6. 信号(Signals)
    • 不是一种典型的IPC机制,但可以用于在进程间发送异步通知,通常用于响应特定的事件,如终止进程或暂停进程。
  7. 远程过程调用(RPC)
    • 允许一个进程调用远程机器上另一个进程的函数,隐藏了网络通信的细节,提供了一个简单的接口来调用远程函数。

管道

  • 管道存在于内存中

  • 读写数据都是一次性的

无名管道:

fd[0]:管道的输出端:读端(文件读入端)

fd[1]:管道的输入端:写端(文件的写出端)

pipe():返回值:成功:0 失败:-1

1、本质上:一种文件

2、特点:1、半双工通信:数据在同一时刻只能在一个方向上流通

​ 2、管道的两端,一边读,一遍写,成为读端和写端

​ 3、数据读取遵循先进先出的原则

​ 4、读取操作室一次性的:读过的数据会被管道抛弃

​ 5、管道的数据室无格式的

文字描述符:用于对文件读写的标识符

read/write:阻塞型函数:未满足条件就会阻塞进程的函数(会导致全进程被挂起)

read(int _fd,void* _buff,size_t _nbytes)
ps:int fd=open("./FIFO",O_RDONLY //以只读形式打开);
    char msg[100] = {0};
    read(fd,msg,100);
    Printf("读取到的信息是:%s\n", msg);
write(int _fd,void* _buff,size_t _nbytes)
ps: char msg[100] = {"helloworld!"};
    write(fd,msg,100);
    printf("写入的信息是:%s\n", msg);
    return 0;

fd:文件描述符 buff:读取到的内存 _nbytes:读取长度

有名管道:(FIFO):

1、本质:在本地磁盘上的一个特殊文件

2、特点:1、半双工通信:数据在同一时刻只能在一个方向上流通

​ 2、管道的两端,一边读,一遍写,成为读端和写端

​ 3、数据读取遵循先进先出的原则

​ 4、读取操作室一次性的:读过的数据会被管道抛弃

​ 5、管道的数据室无格式的

mkfifo(const char *__path, mode_t __mode)

__path:绝对路径

__mode:权限、打开方式

#define	S_IRUSR	__S_IREAD	/* Read by owner.  被拥有者读*/
#define	S_IWUSR	__S_IWRITE	/* Write by owner.  被拥有者写*/
#define	S_IXUSR	__S_IEXEC	/* Execute by owner.  被拥有者执行*/
/* Read, write, and execute by owner.  */
#define	S_IRWXU	(__S_IREAD|__S_IWRITE|__S_IEXEC)   //全权限:可读可写可执行

创建管道之后进行open

int open(const char *__file, int __oflag, ...)

返回值是一个文件描述符fd[ ] ,打开失败返回值为-1

信号

1、定义:软件中断:在软件层面上对中断机制的一种模拟

2、特点:异步通信方式

常用信号:ctrl + c 中断信号 sigint

​ ctrl + \ 退出信号 IGQUIT

​ ctrl + z 停止信号 SIGSTOP

缺省处理:退出进程

kill 函数:给进程发信号

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

alarm函数:定时函数

alarm(2);

signal: 自定义信号处理函数

    void sighandler(int signal)//当定时器传入信号为SIGALRM时,清理屏幕
{
    if(signal==SIGALRM)
    {
        system("clear");
    }
}

    signal(SIGALRM, sighandler);    //在闹钟信号触发时,传入sighandler函数中
    alarm(5);

效果:每五秒钟清理一次屏幕

raise:给自己发信号

    sleep(2);
    raise(SIGALRM);  //=kill(getpid(),)
    sleep(10);

pause函数:进程挂起,直到信号到达才结束

pause();

killall命令:

通过进程名字杀死进程

消息队列

存放在内存中的链表,由内核进行维护

特点:1、消息是有格式的

​ 2、消息是有类型的

​ 3、消息的读取不是先进先出

​ 4、允许多个进程同时读取

​ 5、消息只能读一次

​ 6、消息队列具有唯一标识符

#include<sys/ipc.h>//进程间通信头文件
#include<sys/msg.h>
ps:消息队列是怎么做到有类型的
struct Msg
{
    long MsgType;//强制要求前八个字节放消息类型
};
//1、获取键值
key_t ftok(const char *__pathname, int __proj_id)   //typedef int key_t  key_t本质上是int
key_t key=ftok("./",1);//获取IPC的唯一键值

//2、创建消息队列,获得队列ID
int msgget(key_t __key, int __msgflg)
__msgflg:
#define IPC_CREAT	01000		/* 创建消息队列 */
#define IPC_EXCL	02000		/* 检测消息队列是否存在 */
#define IPC_NOWAIT	04000        /*不阻塞*/
//创建消息队列,返回值:消息队列的ID   -1:错误
int msgID=msgget(key, IPC_CREAT);   //终端:ipcs -q 查看消息队列  //ipcrm -q (根据查看填入msqid) 删除消息队列
ps:如果提示权限问题:int msgID=msgget(key, IPC_CREAT | 0777);//给777权限

//3、向消息队列中传入消息
int msgsnd(int __msqid, const void *__msgp, size_t __msgsz, int __msgflg)
__msgflg:
0:阻塞直到满足条件
IPC_NOWAIT:不阻塞,消息不能直接发送就立即返回
struct Msg m;
m.MsgType = 1;
msgsnd(msgID, &m, sizeof(m), 0);//返回值:-1:错误  0:正确

//4、从消息队列中读入消息
ssize_t msgrcv(int __msqid, void *__msgp, size_t __msgsz, long __msgtyp, int __msgflg)
msgrcv(msgID,&m,sizeof(m),1,0)
这里的1是m.MsgType = 1;,自己定义的类型1
0:阻塞直到满足条件

//5、删除消息队列
int msgctl(int __msqid, int __cmd, struct msqid_ds *__buf)
msgctl(msgID, IPC_RMID, NULL);
__cmd:
#define IPC_RMID	0		/*删除消息队列*/
#define IPC_SET		1		/* 将备份导入到消息队列 */
#define IPC_STAT	2		/* 把消息队列的数据导入到备份中 */
struct msqid_ds *__buf(消息队列的备份结构体的指针):
struct msqid_ds DS :消息队列的备份结构体
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值