自己家里做网站网速慢,网站建设应该学什么,点石家装,最好看免费中文上次结束了基础IO#xff1a;Linux#xff1a;基础IO#xff08;三.软硬链接、动态库和静态库、动精态库的制作和加载#xff09; 文章目录 1.认识进程间通信2.管道2.1匿名管道2.2pipe()函数 —创建匿名管道2.3匿名管道的四种情况2.4管道的特征 3.基于管道的进程池设计4.命…上次结束了基础IOLinux基础IO三.软硬链接、动态库和静态库、动精态库的制作和加载 文章目录 1.认识进程间通信2.管道2.1匿名管道2.2pipe()函数 —创建匿名管道2.3匿名管道的四种情况2.4管道的特征 3.基于管道的进程池设计4.命名管道4.1引入与性质4.2命令行创建4.3程序中创建命名管道写个小项目项目规划Cnmm.hppPipeClient.cppPipeServe.cpp 5.System V共享内存5.1相关函数介绍 1.认识进程间通信
我们通过之前的知识知道进程具有独立性。两个进程之间时不能进行数据的直接传递的 但我们之前学校的fork函数不是能传递子进程的pid给父进程吗——这个严格来说不算通信 为什么我们需要进程间通信 数据传输一个进程需要将自己的数据发送给另一个进程。这种通信方式可以实现进程之间的数据交换和共享从而实现协作和协同工作。资源共享多个进程之间共享同样的资源如共享内存、共享文件等。通过进程间通信可以实现多个进程对同一资源的访问和操作提高资源的利用率和效率。通知事件一个进程需要向另一个或一组进程发送消息通知它们发生了某种事件如进程终止、资源可用等。通过通知事件进程可以及时响应和处理其他进程的状态变化实现进程之间的协作和同步。进程控制有些进程希望完全控制另一个进程的执行如调试进程需要拦截另一个进程的陷入和异常并能够及时知道其状态改变。通过进程控制可以实现对其他进程的监控、调试和管理确保系统的稳定和安全运行。 我们往往需要多个进程协同来完成一些任务 进程间通信是什么 一个进程能把自己的数据给另外一个进程一直 本质让不同的进程看到同一份资源(一般都是要由OS提供) 如何进行进程间通信 我们要有一个来进行数据交换的空间一般是内存。不是直接去另外一个进程里拿这样会破坏进程的独立性这段空间不能由这双方来提供。由OS话事人来提供OS提供的”空间“有不同的样式就决定了有不同的通信方式
那么OS提供的样式有
管道匿名、命名共享内存消息队列信号量 2.管道 基于文件的让不同进程看到同一份资源的通信方式叫做管道 管道只能被设计成为单向通信 在Linux中管道确实可以被视为一种机制同时也是一种特殊的文件类型。这种双重性来自于Linux操作系统的设计和其对所有资源采取的抽象化处理方式。 作为一种机制管道用于进程间通信IPC。它允许一个进程的输出直接成为另一个进程的输入从而实现了数据的快速传递。这种机制大大简化了进程间的通信过程提高了通信效率。 从文件的角度来看管道在Linux中被实现为一种特殊的文件类型。这意味着管道具有文件的某些属性和操作方式比如可以通过文件描述符进行打开、读取、写入和关闭等操作。然而与普通文件不同的是管道并不在磁盘上占用实际的物理空间它的内容存储在内核的缓冲区中只在内存中存在。 这种双重性使得管道既具有机制的灵活性又具有文件的可操作性。它可以在不同的进程之间建立连接实现数据的传递和共享同时也可以通过标准的文件操作接口进行访问和控制。 为了支持管道通信OS提供了一个接口pipe
2.1匿名管道
匿名管道Anonymous PipeLinux中提供的一种进程间通信IPC机制。匿名管道没有名字它们仅存在于创建它们的进程及其子进程之间并且一旦这些进程终止管道也将随之消失。
匿名管道的主要特点如下
单向通信匿名管道是半双工的这意味着数据只能在一个方向上流动。通常一个进程向管道写入数据而另一个进程从管道读取数据。如果需要双向通信则需要创建两个管道一个用于每个方向。亲缘关系匿名管道只能用于具有亲缘关系的进程之间即一个进程和它的子进程之间。这是因为管道的文件描述符是通过fork()系统调用在父子进程之间复制的。自动管理当所有使用管道的文件描述符都被关闭时管道将自动被删除。这意味着不需要像命名管道那样显式地打开和关闭它。内存中的缓冲区管道实际上是一个在内核中维护的缓冲区用于存储从写入端发送但尚未被读取端读取的数据。这个缓冲区的大小是有限的如果写入的数据超过了缓冲区的大小写操作可能会被阻塞直到有空间可用。 管道文件的数据是存储在内存中的是内存级的文件而不是磁盘上。这使得对管道的访问速度非常快类似于对内存的直接访问 匿名管道是通过创建子进程而子进程会继承父进程的相关属性信息来实现不同的进程看到同一份资源 通过管道一个进程写端可以将数据发送给另一个进程读端实现数据的共享和传递。当读端从管道中读取数据时这些数据会被从内核的缓冲区中移除或称为消费从而为写端提供了更多的空间来写入新的数据 在C语言中可以使用pipe()函数来创建一个匿名管道。这个函数接受一个包含两个文件描述符的数组作为参数并返回两个文件描述符一个用于读操作另一个用于写操作。然后可以使用fork()创建一个子进程并在父进程和子进程之间使用这些文件描述符进行通信。
2.2pipe()函数 —创建匿名管道 pipe函数用于创建管道这是一种特殊的文件用于连接一个程序的标准输出和另一个程序的标准输入从而实现这两个程序之间的通信。在C语言中函数原型为int pipe(int pipefd[2]);
参数
pipe函数接受一个整型数组作为参数这是个输出型参数即int pipefd[2]。这个数组用于存储管道的两个文件描述符pipefd[0]表示管道的读端而pipefd[1]表示管道的写端。
作用
调用pipe函数后系统会创建一个匿名管道并将这个管道的两个端点一个用于读一个用于写的文件描述符分别赋值给pipefd[0]和pipefd[1]。这样一个进程就可以通过pipefd[1]向管道写入数据而另一个进程则可以通过pipefd[0]从管道中读取数据。这种机制使得两个进程之间可以通过管道进行通信。
返回值
如果pipe函数成功创建了管道则返回0。如果创建失败则返回-1并将错误原因存储在全局变量errno中。可能的错误原因包括
EMFILE进程已达到其文件描述符的最大数量。ENFILE系统已达到其文件描述符的最大数量。EFAULT传递给pipe函数的数组地址不合法。
#includestdio.h
#includestring.h
#includestdlib.h
#includeunistd.h
#includesys/types.h
#includesys/wait.hvoid writer(int wfd)//写端的操作
{const char *str hi father, I am child;char buffer[128];int cnt 0;pid_t pid getpid();while(1){//先调用snprintf向buffer数组里写然后在把buffer数组写到fd为wfd的文件里(这里就是管道的写端)snprintf(buffer, sizeof(buffer), message: %s, pid: %d, count: %d\n, str, pid, cnt);write(wfd, buffer, strlen(buffer));cnt;sleep(1);}
}void reader(int rfd)//读端的操作
{char buffer[1024];while(1){ssize_t n read(rfd, buffer, sizeof(buffer)-1);(void)n;//没有使用这个 n 变量。如果编译器被配置为警告未使用的变量那么它就会为 n 发出一个警告printf(father gets a message: %s, buffer);}
}int main()
{//创建管道int pipefd[2];int n pipe(pipefd);// pipefd[0]--read pipefd[1]--write 0是写端1是读端// 0--嘴巴 读书 1--钢笔 写字if(n 0) return 1;//创建子进程pid_t id fork();if(id 0){//child: w 我们让子进程来写close(pipefd[0]);//那么就要关闭读端writer(pipefd[1]);exit(0);}// father: r我们让父进程来读close(pipefd[1]);//那么就要关闭写端reader(pipefd[0]);wait(NULL);return 0;
}2.3匿名管道的四种情况 管道内部没有数据而且子进程不关闭自己的写端文件fd 读端(父)就要阻塞等待直到pipe有数据 管道中没有数据时读端继续读取的默认行为是阻塞当前正在读取的进程。在这种情况下进程会进入等待状态其进程控制块PCB会被放置在管道文件的等待队列中。只要管道中没有新的数据到来读端进程就会一直阻塞等待 管道内部被写满而且读端父进程不关闭自己的fd写端子进程写满之后就要阻塞等待 管道具有固定的缓冲区大小当缓冲区中的数据量达到上限时写端进程就会被阻塞直到有读端进程从管道中读取数据并释放缓冲区空间 #includestdio.h
#includestring.h
#includestdlib.h
#includeunistd.h
#includesys/types.h
#includesys/wait.hvoid writer(int wfd)//写端的操作
{const char *str hi father, I am child;char buffer[128];int cnt 0;pid_t pid getpid();while(1){char chA;write(wfd, ch, 1);cnt;printf(cnt%d\n,cnt);}
}void reader(int rfd)//读端的操作
{char buffer[1024];while(1){sleep(10);ssize_t n read(rfd, buffer, sizeof(buffer)-1);(void)n;//没有使用这个 n 变量。如果编译器被配置为警告未使用的变量那么它就会为 n 发出一个警告printf(father gets a message: %s, buffer);}
}int main()
{//创建管道int pipefd[2];int n pipe(pipefd);// pipefd[0]--read pipefd[1]--write 0是写端1是读端// 0--嘴巴 读书 1--钢笔 写字if(n 0) return 1;//创建子进程pid_t id fork();if(id 0){//child: w 我们让子进程来写close(pipefd[0]);//那么就要关闭读端writer(pipefd[1]);exit(0);}// father: r我们让父进程来读close(pipefd[1]);//那么就要关闭写端reader(pipefd[0]);wait(NULL);return 0;
}不再向管道写入数据并且关闭了写端子进程文件描述符时读端父进程可以继续从管道中读取剩余的数据直到管道中的数据全部被读取完毕。最后就会读到返回值为0表示读结束类似读到了文件的结尾 读端关闭其文件描述符并且不再读取数据时如果写端继续向管道写入数据操作系统会发送一个SIGPIPE信号给写端进程。默认情况下这个信号会终止写端进程。SIGPIPE信号是一个用于处理管道写端在写操作时无读端接收的情况的信号。 SIGPIPE信号信号编号为13的发送是为了通知写端进程其写操作因为管道的另一端没有读端而不再有意义。这是一种保护机制防止写端进程在没有读端的情况下无限期地等待或继续写入数据到一个不再被读取的管道中。 #includestdio.h
#includestring.h
#includestdlib.h
#includeunistd.h
#includesys/types.h
#includesys/wait.hvoid writer(int wfd)//写端的操作
{int cnt 0;while(1){sleep(1);char chA;write(wfd, ch, 1);cnt;printf(cnt%d\n,cnt);}//子进程一直写
}void reader(int rfd)//读端的操作
{int cnt8;char buffer[1024];while(1){sleep(1);ssize_t n read(rfd, buffer, sizeof(buffer)-1);if(n0){printf(father get a message: %s, n : %ld\n, buffer, n);}else if(n0){printf(reading has done: %s %ld\n, buffer,n);break;}else {break;}cnt--;if(cnt0){break;}}close(rfd);//8秒后父进程不再读直接关闭printf(end);
}int main()
{//创建管道int pipefd[2];int n pipe(pipefd);// pipefd[0]--read pipefd[1]--write 0是写端1是读端// 0--嘴巴 读书 1--钢笔 写字if(n 0) return 1;//创建子进程pid_t id fork();if(id 0){//child: w 我们让子进程来写close(pipefd[0]);//那么就要关闭读端writer(pipefd[1]);exit(0);}// father: r我们让父进程来读close(pipefd[1]);//那么就要关闭写端reader(pipefd[0]);int status0;pid_t ridwaitpid(id,status,0);printf(exit code: %d, exit signal: %d\n,WEXITSTATUS(status),status0x7f);return 0;
}2.4管道的特征 匿名管道自带同步机制在匿名管道中写端在写数据且没有写完时读端是不可能访问管道这块公共资源的。这种机制确保了数据的完整性和一致性避免了数据冲突和错误 管道Pipe是一种常用于具有血缘关系进程间通信的机制特别是在父子进程之间。这里的“血缘关系”指的是进程之间的创建关系即一个进程创建了另一个进程它们之间存在直接的父子关系 管道pipe是面向字节流的这意味着管道在传输数据时是以字节为单位进行处理的。无论是字符、整数还是其他类型的数据都会被转换成字节序列进行传输。因此管道不关心数据的具体格式或类型只负责将数据以字节流的形式从一个进程传递到另一个进程 管道pipe是半双工的它只能在一个方向上传输数据属于单向通信的特殊概念。具体来说一个管道有一个输入端和一个输出端数据可以从输入端流入管道并从输出端流出。但管道不允许数据在相反的方向上流动即不能从输出端流回输入端 半双工Half Duplex数据传输指的是数据可以在一个信号载体的两个方向上传输但是不能同时传输。也就是说在一个时间点数据只能在一个方向上流动 父子进程退出后管道会自动释放。这是由操作系统的内存管理机制决定的。当进程结束时操作系统会回收其占用的所有资源包括打开的文件、管道、网络连接等 我们之前在命令行里使用的|其实就是匿名管道在命令行中当我们使用|来连接两个命令时实际上是在这两个命令之间创建了一个匿名管道。这使得前一个命令的输出能够直接传输给后一个命令实现了两个命令之间的数据共享和传输
3.基于管道的进程池设计 4.命名管道
4.1引入与性质
我们设想一个这样的情况
当一个进程打开一个文件比如log.txt内核会为该进程创建一个struct file结构体其中包含指向inode结构体、函数指针数组和缓冲区的指针。这个struct file结构体会指向已加载的inode结构体和缓冲区用于表示文件在内核中的信息和缓存文件数据。当另一个进程也打开同一个文件时内核会为该进程创建另一个struct file结构体其中也包含指向相同的inode结构体和缓冲区的指针。这意味着多个进程可以共享相同的inode结构体和缓冲区而不会为每个进程创建一份完全一样的inode结构体和缓冲区。由于inode结构体和缓冲区是在内核中维护的因此多个进程可以共享相同的inode结构体和缓冲区而不需要为每个进程复制一份。这种共享机制可以节省内存空间并确保多个进程对同一文件的操作是一致的。 此时这两个进程就看到了同一块资源log.txt 文件 当两个进程共享同一个文件例如log.txt时它们实际上是在操作同一块资源。这是因为文件系统中的路径和文件名是唯一的所以无论哪个进程打开同一个路径下的文件都会访问到同一个文件。 在多个进程共享文件时它们可以通过共享同一个缓冲区来进行数据交换。这个缓冲区可以被看作是一个管道用于在进程之间传递数据。通过这种方式进程可以实现数据共享和通信。 在上面这种情况下这个管道缓冲区可以被称为命名管道named pipe。 命名管道是一种特殊的文件类型它允许进程之间通过文件系统进行通信。通过路径文件名来确定唯一的路径文件名来找到并访问这个管道多个进程可以通过打开同一个命名管道来实现数据交换。 在这种情况下这个管道不需要与磁盘进行交互因为数据是在内存中进行传递的。进程通过读取和写入管道来实现数据共享而不需要直接与磁盘进行交互。 4.2命令行创建
命名管道Named Pipe是一种特殊的文件用于进程间通信。它是一种半双工通信方式允许一个或多个进程之间通过读写同一个文件来进行通信。 创建命名管道 命名管道是通过调用mkfifo系统调用来创建的。命名管道在文件系统中以文件的形式存在但实际上它是一个FIFOFirst In First Out的通信通道。创建命名管道的语法为 mkfifo 管道名称打开和关闭命名管道 命名管道可以像普通文件一样被打开和关闭。进程可以通过open系统调用打开一个命名管道文件并通过close系统调用关闭它。在打开命名管道时进程需要指定相应的读写权限。 读写数据 进程可以通过打开的文件描述符对命名管道进行读写操作。一个进程往管道中写入数据另一个进程从管道中读取数据。命名管道是阻塞的如果写入进程写入数据时没有进程读取数据写入进程会被阻塞直到有进程读取数据。 进程间通信 命名管道通常用于实现进程间通信特别是在父子进程或者**不相关进程之间**。一个进程可以向命名管道写入数据另一个进程可以从命名管道读取数据实现了进程间的数据交换。
4.3程序中创建命名管道 mkfifo函数是一个UNIX系统中用于创建命名管道named pipe的函数。它的作用是在文件系统中创建一个特殊类型的文件这个文件可以被多个进程用来进行进程间通信。
在C语言中可以使用mkfifo函数来创建一个命名管道其原型如下
int mkfifo(const char *pathname, mode_t mode);pathname参数是指定要创建的命名管道的路径和文件名。mode参数是指定创建的管道的权限模式通常以八进制表示例如0666。
使用mkfifo函数创建命名管道后其他进程可以通过打开这个路径文件名来访问这个管道从而实现进程间的通信。一旦创建了命名管道它就可以在文件系统中像普通文件一样被打开、读取和写入。
写个小项目
项目规划 Cnmm.hpp管道的封装头文件的包含、宏定义等任务PipeClient.cpp客户端进行管道的写入PipeServe.cpp服务端服务器进行管道的创建、读取 Cnmm.hpp
#ifndef __COMM_HPP__
#define __COMM_HPP__#include iostream
#include string
#include cerrno
#include cstring
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include fcntl.husing namespace std;#define Mode 0666
#define Path ./fifoclass Fifo
{
public:Fifo(const string path) : _path(path){umask(0);int n mkfifo(_path.c_str(), Mode);if (n 0){cout mkfifo success endl;}else{cerr mkfifo failed, errno: errno , errstring: strerror(errno) endl;}}~Fifo(){int n unlink(_path.c_str());if (n 0){cout remove fifo file _path success endl;}else{cerr remove failed, errno: errno , errstring: strerror(errno) endl;}}private:string _path; // 文件路径文件名
};#endif//条件编译结束整体上使用一个条件编译 在C头文件中通常会使用条件编译指令来防止头文件被多次包含以避免重复定义的问题。条件编译指令的一般结构如下 #ifndef __HEADER_NAME__
#define __HEADER_NAME__// 头文件内容#endif#ifndef __HEADER_NAME__这是条件编译指令的开始标记用于检查是否已经定义了名为__HEADER_NAME__的宏。如果之前没有定义这个宏那么下面的代码将被执行。#define __HEADER_NAME__在条件编译指令的开始处定义名为__HEADER_NAME__的宏表示这个头文件已经被包含过了。// 头文件内容在这个部分可以放置头文件的内容包括类的定义、函数的声明等。#endif这是条件编译指令的结束标记表示条件编译的范围结束。 #ifndef __COMM_HPP__是条件编译指令的开始标记而#endif是条件编译指令的结束标记。 cerr cerr是C标准库中的标准错误流它用于输出错误信息到标准错误设备通常是显示器。与cout标准输出流类似cerr也是一个对象可以使用插入运算符来将数据插入到cerr中进行输出。与cout不同的是cerr通常用于输出错误消息而不是普通的程序输出。它是线程安全的可以在多线程环境中使用。 errno errno是一个全局变量通常定义在cerrno头文件中用于存储函数调用发生错误时的错误码。当某个函数发生错误时它会设置适当的错误码到errno中以便程序能够检测和处理错误。错误码是整数类型每个错误码对应于一种特定类型的错误。可以通过查看系统的错误码表来了解每个错误码的含义。 strerror strerror是一个C标准库函数通常定义在cstring或string.h头文件中用于将错误码转换为对应的错误消息字符串。strerror接受一个错误码作为参数并返回一个指向描述该错误的字符串的指针。通过调用strerror(errno)可以获取与当前errno值对应的错误消息字符串以便程序输出或记录错误信息。
PipeClient.cpp
#include Comm.hppint main()
{// 打开管道进行写入最后关闭int wfd open(Path, O_WRONLY | O_CREAT); // 以只写方式打开if (wfd 0){cerr open failed, errno: errno , errstring: strerror(errno) endl;return 1;}string buffer; // 开始写入while (true){cout please write your message: endl;getline(cin, buffer);ssize_t n write(wfd, buffer.c_str(), buffer.size());if (n 0){cerr write failed, errno: errno , errstring: strerror(errno) endl;break;}}close(wfd);return 0;
}PipeServe.cpp
#include Comm.hpp
#include unistd.hint main()
{Fifo fifo(Path);// 打开管道进行读取最后关闭int rfd open(Path, O_RDONLY); // 以只读方式打开if (rfd 0){cerr open failed, errno: errno , errstring: strerror(errno) endl;return 1;}char buffer[1024];//开始读取while (true){ssize_t n read(rfd, buffer, sizeof(buffer) - 1);if (n 0){buffer[n] \0;cout client say : buffer endl;}else if (n 0){cout client quit, me too!! endl;break;}else{cerr read failed, errno: errno , errstring: strerror(errno) endl;break;}}close(rfd);return 0;
}这里我自己有个疑问本来读端是一直堵塞在read函数的我们一输入abcde第一次read就能读取完然后输出。下一次循环就应该接着读读到末尾返回0了吧 但为什么这里是接着阻塞呢 在非阻塞模式下如果读取到文件末尾没有更多的数据可读取read 函数会立即返回 0。在阻塞模式下read 函数会阻塞等待直到有数据可读取或者发生错误它不会因为读取到文件末尾而返回 0。相反只有当管道被关闭或者读取操作被中断时read 函数才会返回 0。默认都是阻塞模式 文件描述符的阻塞模式和非阻塞模式指的是在进行I/O操作时的行为方式。 阻塞模式 在阻塞模式下当进行I/O操作时如果数据尚未准备好或者操作无法立即完成程序会被阻塞也就是暂停执行直到操作完成或者出现错误为止。例如在阻塞模式下如果调用read函数读取一个文件描述符但是文件中没有数据可读程序将会被阻塞直到有数据到达为止。类似地如果调用write函数写入数据到一个已满的管道中程序也会被阻塞直到有足够的空间写入数据。 非阻塞模式 在非阻塞模式下进行I/O操作时如果操作无法立即完成程序不会被阻塞而是立即返回一个错误或者一个特定的状态码提示当前操作无法立即完成。例如在非阻塞模式下如果调用read函数读取一个文件描述符但是文件中没有数据可读read函数将立即返回一个错误码而不会等待数据到达。类似地如果调用write函数写入数据到一个已满的管道中write函数也会立即返回一个错误码而不会等待空间可用。 5.System V共享内存 实现进程间通信的前提就是如何让不同的进程看到同一份资源 匿名管道我们是通过子进程继承父进程打开的资源命名管道是通过两个进程都打开具有唯一性标识的命名管道文件(路径文件名)共享内存其实是通过OS创建一块shm System V共享内存Shared Memory是一种Linux中用于进程间通信IPC的机制。它允许多个进程访问同一块物理内存区域从而实现数据的快速共享和交换。
原理 在物理内存中申请一块内存空间作为共享内存。将这块内存空间与各个进程的页表建立映射关系使得这些进程在虚拟地址空间中可以看到并访问这块共享内存。通过这种方式多个进程可以像访问自己的内存一样访问共享内存从而实现数据的快速共享和交换。 使用方式 创建使用shmget()系统调用来创建共享内存。这个函数会分配一块指定大小的内存区域并返回一个标识符用于后续对这块共享内存的操作。关联使用shmat()系统调用来将共享内存关联到进程的地址空间。这个函数会将共享内存的地址告诉进程使得进程可以通过这个地址来访问共享内存。取消关联当进程不再需要访问共享内存时可以使用shmdt()系统调用来取消关联。这个函数会断开进程与共享内存之间的映射关系。释放当所有进程都不再需要这块共享内存时可以使用shmctl()系统调用来释放它。这个函数会回收这块内存区域并释放相关的资源。
5.1相关函数介绍
ftok() 函数 Linux中用于生成一个唯一的键值key的系统调用这个键值通常用于在进程间通信IPC中标识共享内存段、消息队列或信号量集。ftok() 函数基于一个已经存在的文件路径和一个非零的标识符通常是一个小的正整数来生成这个键值。
#include sys/ipc.h
#include sys/types.h key_t ftok(const char *pathname, int proj_id);参数:
pathname指向一个已经存在的文件路径的指针。这个文件通常被用作生成键值的“种子”或“基础”。proj_id一个非零的标识符通常是一个小的正整数。这个值将与文件路径一起被用于生成键值。返回值:
如果成功ftok() 函数返回一个唯一的键值key_t 类型该键值可以在后续的 IPC 调用如 shmget(), msgget(), semget() 等中用作参数。如果失败则返回 (key_t) -1 并设置 errno 以指示错误。
shmget()创建或获取共享内存
shmget() 系统调用用于创建一个新的共享内存对象或者如果它已存在则返回该对象的标识符。
函数原型
int shmget(key_t key, size_t size, int shmflg);参数 key一个键用于唯一标识共享内存对象。通常使用ftok()函数生成。 共享内存在内核中同时可以存在很多个OS必须要管理所有的共享内存 如何管理呢?先描述在组织系统中会存在很多共享内存怎么保证多个不同的进程看到的是同共享内存呢? 要给共享内存提供唯一性的标识 key便是那个唯一性标识符。那么为什么这个key要由我们用户来传入呢 如果然系统生成将值返回让我们得到。那我们如何给另外一个进程呢要做到就要有进程间通信这不倒反天罡了 size共享内存的大小以字节为单位。 shmflg权限标志和选项。通常设置为IPC_CREAT如果对象不存在则创建存在的话直接获取和权限如0666。 若设置为IPC_CREAT|IPC_EXCL如果对象不存在则创建存在的话出错返回
返回值成功时返回共享内存对象的标识符失败时返回-1并设置errno。
shmat()将共享内存关联到进程的地址空间
shmat() 系统调用用于将共享内存对象关联到调用进程的地址空间。
函数原型
void *shmat(int shmid, const void *shmaddr, int shmflg);参数
shmidshmget()返回的共享内存对象标识符。shmaddr希望将共享内存附加到的进程的地址。如果设置为NULL则系统选择地址。shmflg通常设置为0或SHM_RND使附加地址向下舍入到最接近的SHMLBA边界。
返回值成功时返回共享内存附加到进程的地址失败时返回(void *)-1并设置errno。
shmdt()取消共享内存的关联
shmdt() 系统调用用于取消之前通过shmat()附加到进程的共享内存的关联。
函数原型
int shmdt(const void *shmaddr);参数
shmaddrshmat()返回的共享内存附加到进程的地址。
返回值成功时返回0失败时返回-1并设置errno。
shmctl()控制共享内存
shmctl() 系统调用用于获取或设置共享内存的属性或者删除共享内存对象。
函数原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);参数
shmid共享内存对象标识符。cmd要执行的操作。例如IPC_RMID用于删除共享内存对象IPC_STAT用于获取其状态。buf指向shmid_ds结构的指针用于传递或接收共享内存的状态信息。
返回值成功时返回0失败时返回-1并设置errno。 今天就到这里了也是结束了期末周现在就开始正常更新啦 文章转载自: http://www.morning.qmncj.cn.gov.cn.qmncj.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.sdkaiyu.com.gov.cn.sdkaiyu.com http://www.morning.wmnpm.cn.gov.cn.wmnpm.cn http://www.morning.dbtdy.cn.gov.cn.dbtdy.cn http://www.morning.tdhxp.cn.gov.cn.tdhxp.cn http://www.morning.ndcf.cn.gov.cn.ndcf.cn http://www.morning.tstkr.cn.gov.cn.tstkr.cn http://www.morning.wztnh.cn.gov.cn.wztnh.cn http://www.morning.zlrrj.cn.gov.cn.zlrrj.cn http://www.morning.tmsxn.cn.gov.cn.tmsxn.cn http://www.morning.lsnbx.cn.gov.cn.lsnbx.cn http://www.morning.tkztx.cn.gov.cn.tkztx.cn http://www.morning.zqybs.cn.gov.cn.zqybs.cn http://www.morning.gbtty.cn.gov.cn.gbtty.cn http://www.morning.hqgxz.cn.gov.cn.hqgxz.cn http://www.morning.rczrq.cn.gov.cn.rczrq.cn http://www.morning.wyrsn.cn.gov.cn.wyrsn.cn http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.hhfwj.cn.gov.cn.hhfwj.cn http://www.morning.beiyishengxin.cn.gov.cn.beiyishengxin.cn http://www.morning.bkfdf.cn.gov.cn.bkfdf.cn http://www.morning.wwsgl.com.gov.cn.wwsgl.com http://www.morning.spnky.cn.gov.cn.spnky.cn http://www.morning.xkjrq.cn.gov.cn.xkjrq.cn http://www.morning.rgxll.cn.gov.cn.rgxll.cn http://www.morning.zwzwn.cn.gov.cn.zwzwn.cn http://www.morning.sjbty.cn.gov.cn.sjbty.cn http://www.morning.hmfxl.cn.gov.cn.hmfxl.cn http://www.morning.xdfkrd.cn.gov.cn.xdfkrd.cn http://www.morning.stwxr.cn.gov.cn.stwxr.cn http://www.morning.gxcit.com.gov.cn.gxcit.com http://www.morning.ymfzd.cn.gov.cn.ymfzd.cn http://www.morning.dlgjdg.cn.gov.cn.dlgjdg.cn http://www.morning.prkdl.cn.gov.cn.prkdl.cn http://www.morning.tqbyw.cn.gov.cn.tqbyw.cn http://www.morning.dwrjj.cn.gov.cn.dwrjj.cn http://www.morning.mxtjl.cn.gov.cn.mxtjl.cn http://www.morning.tcylt.cn.gov.cn.tcylt.cn http://www.morning.nkhdt.cn.gov.cn.nkhdt.cn http://www.morning.rrdch.cn.gov.cn.rrdch.cn http://www.morning.mphfn.cn.gov.cn.mphfn.cn http://www.morning.jwsrp.cn.gov.cn.jwsrp.cn http://www.morning.fdlyh.cn.gov.cn.fdlyh.cn http://www.morning.lwcgh.cn.gov.cn.lwcgh.cn http://www.morning.aiai201.cn.gov.cn.aiai201.cn http://www.morning.xnltz.cn.gov.cn.xnltz.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.rbffj.cn.gov.cn.rbffj.cn http://www.morning.jftl.cn.gov.cn.jftl.cn http://www.morning.bnjnp.cn.gov.cn.bnjnp.cn http://www.morning.pjrgb.cn.gov.cn.pjrgb.cn http://www.morning.sftrt.cn.gov.cn.sftrt.cn http://www.morning.kwqt.cn.gov.cn.kwqt.cn http://www.morning.bwdnx.cn.gov.cn.bwdnx.cn http://www.morning.krkwh.cn.gov.cn.krkwh.cn http://www.morning.fyxr.cn.gov.cn.fyxr.cn http://www.morning.wtcd.cn.gov.cn.wtcd.cn http://www.morning.ybhjs.cn.gov.cn.ybhjs.cn http://www.morning.mymz.cn.gov.cn.mymz.cn http://www.morning.rnnts.cn.gov.cn.rnnts.cn http://www.morning.banzou2034.cn.gov.cn.banzou2034.cn http://www.morning.xhqwm.cn.gov.cn.xhqwm.cn http://www.morning.wtdhm.cn.gov.cn.wtdhm.cn http://www.morning.xfcjs.cn.gov.cn.xfcjs.cn http://www.morning.zxxys.cn.gov.cn.zxxys.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.nrfqd.cn.gov.cn.nrfqd.cn http://www.morning.nj-ruike.cn.gov.cn.nj-ruike.cn http://www.morning.qlrwf.cn.gov.cn.qlrwf.cn http://www.morning.mknxd.cn.gov.cn.mknxd.cn http://www.morning.prlgn.cn.gov.cn.prlgn.cn http://www.morning.tjmfz.cn.gov.cn.tjmfz.cn http://www.morning.wtbzt.cn.gov.cn.wtbzt.cn http://www.morning.lgcqj.cn.gov.cn.lgcqj.cn http://www.morning.c7624.cn.gov.cn.c7624.cn http://www.morning.lxhrq.cn.gov.cn.lxhrq.cn http://www.morning.zbkdm.cn.gov.cn.zbkdm.cn http://www.morning.gczqt.cn.gov.cn.gczqt.cn http://www.morning.glswq.cn.gov.cn.glswq.cn