Linux进程

编程入门 行业动态 更新时间:2024-10-24 06:24:17

Linux<a href=https://www.elefans.com/category/jswz/34/1771450.html style=进程"/>

Linux进程

进程的语言

进程间的通信 (IPC) 方式,总归起来主要有如下这些:

1,无名管道 (PIPE) 和有名管道 (FIFO) 。

2,信号 (signal) 。

3,system V-IPC 之共享内存。

4,system V-IPC 之消息队列。

5,system V-IPC 之信号量。

6,套接字

这些通信方式各有各的特点,无名管道是最简单的常用于一对一的亲缘进程间通信的方

式,有名管道存在于文件系统之中,提供写入原子性特征,信号是唯一一种异步通信方式, 共享内存的效率最高,但是要结合信号量等同步互斥机制一起使用,消息队列提供一种带简 单消息标识的通信方式,套接字是一种更为宽泛意义上的进程间通信方式——它允许进程间 跨网络。

 无名管道

常说的管道通常指无名管道 (PIPE) 或者有名管道 (FIFO) ,但实际上套接字也都是 管道。这里先把 PIPE 和 FIFO 的相关接口摆出:

功能

创建无名管道:PIPE

头文件

#include <unistd.h>

原型

int pipe(int pipefd[2]);

参数

pipefd

一个至少具有 2 个 int 型数据的数组,用来存放 PIPE 的读写端描述符

返回值

成功

0

失败

- 1

备注

功能

创建有名管道:FIFO

头文件

#include <sys/types.h>

#include <sys/stat.h>

原型

int mkfifo(const char *pathname, mode_t mode);

参数

pathname

FIFO 的文件名

mode

文件权限

返回值

成功

0

失败

- 1

备注

表  创建无名管道和有名管道的函数接口规范

先来看看 PIPE 。既然叫管道,那么可以想象他就像一根水管,连接两个进程,一个进 程要给另一个进程数据,就好像将水灌进管道一样,另一方就可以读取出来了,反过来也一 样。这是我们对 PIPE 最简单的感官认识。

先来罗列 PIPE 的特征:

1,没有名字,因此无法使用 open( )。

2,只能用于亲缘进程间 (比如父子进程、兄弟进程、祖孙进程……) 通信。

 3,半双工工作方式:读写端分开,一个只能用来读,一个只能用来写。

4,写入操作不具有原子性,因此只能用于一对一的简单通信情形。

5,不能使用 lseek( )来定位:因为他们的数据不能像普通文件那样按块的方式存储在硬盘,而是像一个看不见源头的水龙,无法定位。

6、管道都不可以在共享文件中创建。

PIPE的缺点是:

 他对写操作不做任何保护!即:假如有多个进程或线程同时对 PIPE 进行写操作,那么这些数据很有可能会相互践踏。因此,PIPE 只能用于一对一的亲缘进程通信。

无名管道示例代码如下:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>int main()
{int fd[2];int ret = pipe(fd);if(-1 == ret){perror("open pipe failed");return -1;}char buf[128];char msg[128];pid_t pid = fork();if(pid == 0){read(fd[0],msg,sizeof(msg)-1);//阻塞等待printf("[from child]%s\n",msg);}if(pid > 0){fgets(buf,sizeof(buf),stdin);write(fd[1],buf,strlen(buf));}}
上述代码中,创建一个无名管道父进程负责管道的发送端,子进程负责管道的接受端。

有名管道 

 任何事物的优缺点都是相对的,PIPE 很简单,同时也适用场景比较单一,性能比较弱, 限制条件比较多,如果要在任意进程间通信,并且保证写入有原子性,那么你可以使用 FIFO --- 一种更加强大的管道。

有名管道 FIFO 的特征:

1,有名字,存储于普通文件系统之中。

2,任何具有相应权限的进程都可以使用 open( )来获取 FIFO 的文件描述符。 

3,跟普通文件一样:使用统一的 read( )/write( )来读写。

4,跟普通文件不同:不能使用 lseek( )来定位,原因同 PIPE。

5,具有写入原子性,支持多写者同时进行写操作而数据不会互相践踏。

 6,First In First Out,最先被写入 FIFO 的数据,最先被读出来。

代码示例:写端

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>  //ioctl()
#include <unistd.h>#define PATH "/home/xwq/ls"  //一个宏定义内容是管道存放路径int main()
{//unlink(PATH);  // 如果fifo文件已存在,则先删除// 判断文件是否存在,如果不存在,则创建fifo文件if (access(PATH, F_OK) != 0){int ret = mkfifo(PATH, 0777);if (ret == -1){perror("creat myfifo failed");return -1;}}// 打开fifo文件,返回文件描述符int fifo_fd = open(PATH, O_RDWR);  //权限if (-1 == fifo_fd){perror("open myfifo failed");return -1;}pid_t pid = fork();  // 创建子进程char buf[128];while (1){memset(buf, 0, sizeof(buf));  //清零// 从标准输入获取用户输入fgets(buf, sizeof(buf), stdin);// 将用户输入写入fifo文件write(fifo_fd, buf, strlen(buf));if (strcmp(buf, "exit\n") == 0){break;}}// 关闭文件描述符close(fifo_fd);return 0;
}

读端

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>  //ioctl()
#include <unistd.h>#define PATH "/home/xwq/myfifo"int main()
{if(access(PATH,F_OK) != 0)//判断文件是否存在{int ret = mkfifo(PATH, 0777); // 创建命名管道if(ret == -1){perror("creat myfifo failed");return -1;}}int fifo_fd = open(PATH,O_RDWR); // 打开命名管道if(-1 == fifo_fd){perror("open myfifo failed");return -1;}char buf[128];while(1){memset(buf, 0, sizeof(buf)); // 清空buf数组read(fifo_fd, buf, sizeof(buf)-1); // 读取命名管道中的数据printf("[from jack] %s",buf);    //输出接收到的信息if(strcmp(buf,"exit\n") == 0) // 如果接收到了退出信号,则退出循环  strcmp 字符串的等式判断{break;}}close(fifo_fd); // 关闭命名管道return 0;}

上述代码中

所谓写者:持有文件可写权限的描述符的进程。

所谓读者:持有文件可读权限的描述符的进程

access函数通常用于检查文件或目录是否存在以及是否具有特定权限。它接受文件路径和权限参数,并返回一个整数值,表示访问权限的状态。常见的返回值包括0(表示有访问权限)、-1(表示访问被拒绝)和其他错误代码。

FIFO 跟 PIPE 区别的还有一个最大的不同点在于:FIFO 具有一种所谓写入原子性的特

征,这种特征使得我们可以同时对 FIFO 进行写操作而不怕数据遭受破坏,一个典型应用是 Linux 的日志系统。

日志

日志示例代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>//ioctl()
#include <unistd.h>
#include <time.h>#define PATH "/home/gec/myfifo"int main()
{if(access(PATH,F_OK) != 0){int ret = mkfifo(PATH,0777);if(-1 == ret){perror("creat\n");return -1;}}int fifo_fd = open(PATH, O_WRONLY);if(-1 == fifo_fd){perror("open\n");return -1;}char buf[128];while(1){memset(buf,0,sizeof(buf));time_t curTime;sleep(1);curTime++;time(&curTime);//把时间转换为当前的时间char *curDate = ctime(&curTime);//把时间转换为char *字符串snprintf(buf,sizeof(buf),"[%d]%s",getpid(),curDate);printf("%s\n",buf);write(fifo_fd,buf,strlen(buf));}close(fifo_fd);}

写端

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>//ioctl()
#include <unistd.h>#define PATH "/home/gec/myfifo"int main()
{if(access(PATH,F_OK) != 0)//判断文件是否存在{int ret = mkfifo(PATH, 0777);if(ret == -1){perror("creat myfifo failed");return -1;}}int fifo_fd = open(PATH,O_RDWR);if(-1 == fifo_fd){perror("open myfifo failed");return -1;}int fd = open("./rizhi.txt", O_RDWR | O_CREAT ,0777);if(-1 == fd){perror("open fd failed");return -1;}char buf[128];while(1){memset(buf, 0, sizeof(buf));read(fifo_fd, buf, sizeof(buf)-1);write(fd,buf,strlen(buf));//printf("[from jack] %s",buf);}close(fifo_fd);close(fd);return 0;}

更多推荐

Linux进程

本文发布于:2024-02-24 21:48:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1696770.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:进程   Linux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!