当前位置: 首页 > news >正文

湖南省建设局官方网站导航网站开发工具

湖南省建设局官方网站,导航网站开发工具,国开机考网站界面设计,档案信息网站建设情况管道 在Linux中#xff0c;管道是一种进程间通信方式#xff0c;它允许一个进程#xff08;写入端#xff09;将其输出直接连接到另一个进程#xff08;读取端#xff09;的输入。从本质上说#xff0c;管道也是一种文件#xff0c;但它又和一般的文件有所不同。 具体…管道 在Linux中管道是一种进程间通信方式它允许一个进程写入端将其输出直接连接到另一个进程读取端的输入。从本质上说管道也是一种文件但它又和一般的文件有所不同。 具体来说管道有两种类型无名管道和有名管道。无名管道是指以匿名管道的方式连接两个进程只能在具有亲缘关系的进程之间使用例如父子进程。有名管道则是一种文件类型允许无关进程之间的通信即可以在非亲缘关系的进程之间使用。 无名管道通过文件描述符创建其中文件描述符0stdin用于读取管道的读取端文件描述符1stdout用于写入管道的写入端。有名管道则通过文件系统中的某一个文件名来建立其它进程不论是父子进程还是非亲缘关系进程可以通过打开该文件来进行通信。 使用管道时需要注意以下几点 管道是单向的只能从写入端向读取端传递数据。 管道的大小是有限的当管道被填满时写入端将无法继续写入数据。 读取端不能比写入端更快地读取数据否则会导致读取端阻塞。 有名管道可以跨越不同进程号和主机之间的通信但需要先用 mkfifo 命令创建管道文件。 使用完毕后需要手动删除管道文件。 让我们更深入地理解一下无名管道的工作方式。在Linux中每个进程都有一个标准输入(stdin)一个标准输出(stdout)和一个标准错误(stderr)。无名管道就是利用了进程的stdin和stdout来实现的。 具体来说当一个进程需要将输出发送到另一个进程的输入时可以使用管道。管道的写入端与发送进程的stdout相连接而管道的读取端与接收进程的stdin相连接。这样发送进程的输出就可以直接被接收进程读取。 例如在shell中可以通过“|”符号来实现无名管道的功能。例如“ls -al | grep .txt”命令中管道连接了“ls -al”和“grep .txt”两个命令将“ls -al”命令的输出作为“grep .txt”命令的输入从而实现文件名搜索的功能。 接下来是有名管道。有名管道是一种在文件系统中存在的特殊文件它允许无关的进程之间进行通信。与无名管道只能在具有亲缘关系的进程之间使用不同有名管道可以在任何进程之间使用不论它们是否有亲缘关系。 有名管道通过文件系统中的文件名来建立然后其他进程可以通过打开这个文件来进行通信。使用有名管道时需要先用“mkfifo”命令创建管道文件然后通过文件I/O操作来进行数据的读写。 这就是Linux中的管道概念的基本解释。它是一种非常强大的工具可以用于在不同的进程之间传递数据使得这些进程可以协同工作。 匿名管道 匿名管道通过pipe()函数实现 在Linux中pipe()函数是用于创建无名管道的函数。它允许将一个进程的输出直接连接到另一个进程的输入从而实现在不同进程之间进行数据传递。 pipe()函数在头文件unistd.h中声明其原型如下 int pipe(int pipefd[2]);pipefd是一个包含两个整数的数组用于存储管道的文件描述符。pipefd[0]是管道的读取端pipefd[1]是管道的写入端。 当pipe()函数成功时返回值为0如果出现错误返回值为-1并设置errno来表示错误原因。 注意在父进程和子进程中要分别关闭管道的读取端和写入端以避免资源泄漏。 实例 这个实例的功能建立一个父子进程关系让父进程往管道当中写子进程从管道当中读出来数据 运行结果 命名管道 命名管道通过mkfifo()函数实现 mkfifo是一个在Linux系统中用于创建命名管道的函数也被称为FIFO文件。命名管道是一种特殊类型的文件它被设计为在进程间通信IPC中临时存储数据。FIFO文件通常在shell中使用例如mkfifo /tmp/myfifo。 mkfifo函数的原型如下 #include sys/types.h #include sys/stat.h int mkfifo(const char *pathname, mode_t mode);mkfifo函数需要两个参数 pathname这是要创建的FIFO文件的路径名。 mode这是文件的权限位。这通常包括读、写和执行权限就像在chmod函数中使用的一样。 这个函数会创建一个具有指定权限的FIFO文件如果文件已经存在那么它将被打开并返回一个文件描述符。如果文件不存在那么一个新的文件将被创建。 当mkfifo成功时返回值为0。如果失败返回值为-1并设置全局变量errno以指示错误原因。可能的错误包括权限问题、磁盘空间不足、文件系统错误等。 实例 以下是一个简单的使用mkfifo的例子 #include sys/types.h #include sys/stat.h #include stdio.h int main() { int result mkfifo(/tmp/myfifo, 0666); if (result -1) { perror(mkfifo); return 1; } return 0; }在这个例子中我们尝试在/tmp目录下创建一个名为myfifo的FIFO文件文件的权限设置为0666也就是用户、组和其他所有人都可以读和写。如果创建失败我们打印出错误信息并返回1。 XSI也就是SysV系列进程通信手段 XSI是X/Open公司制定用于进程通信的系统接口是UNIX系统V版本中定义的一组系统调用和信号的集合。在Linux系统中XSI提供了一种用于进程间通信IPC的机制。 XSI进程间通信需要借助系统内核需要创建内核对象内核对象会以整数形式返回给用户态相当于文件描述符也叫IPC标识符。 XSI包括信号量、共享内存、消息队列和信号等进程间通信方式。其中信号量是一个计数器可以对计数器进行加操作和减操作。在加操作时计数器立即返回在减操作时如果计数器的当前值足够进行减操作则减操作不会被阻塞如果计数器的当前值不够进行减操作则阻塞等待直到计数器的值足够进行减操作。 此外XSI还包括一些创建和管理共享内存的函数例如shmget用于创建或获取共享内存shmat用于将共享内存映射到进程的虚拟地址空间等。 在Linux中使用 ipcs 命令可以查看当前系统中存在的各种IPCInner-Process Communication进程间通信机制情况 这三种方式都可以用于有亲缘关系的进程间通信也可以用于没有亲缘关系的进程间通信。 从上图中可以看到每一种通信机制都有一个key这个key的作用就是用来确保没有亲缘关系的两个进程之间通信时拿到的是同一个通信机制有亲缘关系的就很简单了不需要额外的操作因为是fork出来的。 通过ftok函数我们可以拿到通信机制的key。 ftok() ftok是Linux系统下的一个函数主要用于创建唯一的键值称为令牌以用于标识文件系统对象比如共享内存、消息队列和信号量等System V IPC对象。 函数原型如下 #include sys/ipc.h key_t ftok(const char *pathname, int proj_id);ftok函数的参数包括 pathname一个已经存在的文件或目录的路径。该函数将通过这个路径来生成一个唯一的键值。 proj_id这是一个用户定义的整数用于在多个进程之间区分不同的键值。通常如果两个进程使用相同的pathname和proj_id调用ftok那么它们将得到相同的键值。 函数的返回值是一个key_t类型的键值该键值可以被用作System V IPC对象的标识符。如果函数执行失败将返回-1。 值得注意的是虽然ftok函数生成的键值在大多数情况下都是唯一的但在某些情况下两个不同的路径可能会生成相同的键值。此外不同的文件系统或操作系统可能会以不同的方式实现ftok函数因此在不同的系统之间不能保证键值的唯一性。这就是为什么在使用ftok函数时最好选择一个唯一的proj_id并在可能的情况下避免在不同的系统之间共享键值。 IPC机制系列函数 对于每一种IPC机制基本都有 XXXget()、XXXop()、XXXctl()。 其中XXX是每一种IPC机制的缩写消息队列的缩写是msg信号量数组的缩写是sem共享内存是shm 接下来将分别介绍这些函数。 消息队列 Linux下的消息队列机制是System V IPC进程间通信的一种实现方式允许进程之间以消息的形式传递数据。与管道、信号和共享内存等其他IPC机制相比消息队列具有一些独特的优点例如可以跨多个进程传递数据、可以实现异步通信、可以避免忙轮询等。 消息队列的实现原理可以简单地描述为在内存中创建一个队列数据结构进程可以向该队列中写入消息也可以从该队列中读取消息。每个消息都有一个类型和长度类型用于区分不同的消息长度则用于限制消息的大小。进程可以通过指定消息类型来读取或写入特定类型的消息也可以通过指定消息的优先级来控制消息的读写顺序。 在Linux系统中消息队列是通过消息队列标识符也称为消息队列ID来访问的。进程可以使用msgget函数来获取或创建一个消息队列该函数会根据指定的键值生成一个唯一的消息队列标识符。一旦获取到消息队列标识符进程就可以使用msgsnd函数向队列中发送消息或者使用msgrcv函数从队列中接收消息。同时进程还可以使用msgctl函数来控制消息队列的属性例如设置权限、删除队列等。 需要注意的是Linux系统对消息队列的数量和大小都有限制因此在使用消息队列时需要注意这些限制并根据实际需求进行合理的设计和使用。此外由于消息队列是保存在内存中的因此在系统重启后所有的消息队列都会被清空。如果需要长期保存数据可以考虑使用文件或其他持久化存储方式来实现进程间通信。 msgget() msgget是Linux系统下的一个函数用于获取或创建一个消息队列。它是System V消息队列子系统的一部分通常用于进程间的通信IPC。 函数原型如下 #include sys/ipc.h int msgget(key_t key, int flags);msgget函数的参数包括 key一个由ftok函数生成的键值用于标识消息队列。如果这个键值是0那么msgget将创建一个新的消息队列。 flags这是一个标志位用于控制msgget的行为。最常用的标志是IPC_CRE它告诉msgget如果消息队列不存在则创建一个新的消息队列。 函数的返回值是一个指向消息队列的描述符即消息队列的标识符如果函数执行失败将返回-1。 在使用msgget函数时需要注意以下几点 消息队列是进程间通信的一种方式因此需要谨慎地使用避免在多个进程之间造成混乱。 消息队列的创建和使用都需要使用适当的权限(即flags参数需要按位或上一个权限值)。一般来说只有具有适当权限的用户或进程才能创建和使用消息队列。 消息队列是有限制的因此在使用时需要了解其限制例如消息的最大长度和队列的最大数量等。 消息队列在使用完毕后需要使用msgctl函数来释放和删除。 msgop() msgop并不是Linux下的一个具体函数指的是涉及消息队列的一系列操作。是和消息队列相关的函数比如msgsnd、msgrcv和msgctl等。 msgsnd: 此函数用于将消息添加到消息队列中。它接受四个参数消息队列的标识符、指向要发送的消息的指针、消息的大小以及一个标志位。这个函数在成功时返回0在失败时返回-1。 msgrcv: 此函数用于从消息队列中接收消息。它接受五个参数消息队列的标识符、指向接收消息的缓冲区的指针、缓冲区的大小、要接收的消息的类型以及一个标志位。这个函数在成功时返回接收到的消息的大小在失败或没有消息可接收时返回-1。 msgctl: 此函数用于控制消息队列包括设置权限、获取状态以及删除消息队列等操作。它接受三个参数消息队列的标识符、要执行的操作以及一个可选的参数该参数根据要执行的操作而有所不同。这个函数在成功时返回0在失败时返回-1。 在使用这些函数时你需要注意一些事项 首先你需要使用msgget函数来获取或创建一个消息队列。这个函数会返回一个唯一的消息队列标识符你可以使用这个标识符来进行后续的消息发送和接收操作。 其次你需要注意消息的大小和类型。每个消息都有一个大小和一个类型大小用于限制消息的长度类型用于区分不同的消息。你可以在发送和接收消息时指定消息的大小和类型。 最后你需要注意权限和错误处理。只有具有适当权限的进程才能创建和使用消息队列。同时你需要检查函数的返回值以处理可能的错误。 实例 建立三个文件proto就是协议用来约定双方的对话格式sender为发送方发送一个学生信息rcver为接收方接收该学生信息 proto.h: #ifndef PROTO_H__#define PROTO_H__//对话双方需要拿到同一个msg id那么就必须要得到同一个key值 //所以我们在协议中约定好ftok的两个参数以确保它们拿到的是同一个key //KEYPATH就是ftok函数的第一个参数 #define KEYPATH /etc/services //KEYPROJ 是第二个参数用字母是因为这样就能知道其为一个整形有单位比较规范 #define KEYPROJ g #define NAMESIZE 32//需要发送的学生信息格式的封装 struct msg_st{long mtype;//这个是由msgrcv函数的第二个参数消息格式必须要的表示消息类型本例用不到但必须存在char name[NAMESIZE];int math;int chinese; };#endif rcver.c: #include stdio.h #include stdlib.h #include sys/types.h #include sys/ipc.h #include sys/msg.h#include proto.hint main(){key_t key;struct msg_st rbuf;int msgid;//先拿到keykey ftok(KEYPATH,KEYPROJ);if(key 0){perror(ftok());exit(1);}//根据拿到的key创建消息队列实例,注意要按位或上权限信息嗷msgid msgget(key,IPC_CREAT|0600);if(msgid 0){perror(msgget());exit(1);}//从消息队列中拿到数据//第一个参数是消息队列实例的id值//第二个参数是接收到的消息数据所要存放的地方//第三个参数表示接收来的数据类型大小自己需要的数据的大小所以-long其实不减也行//第四个参数指定要接收的消息的类型为0就是不挑//第五个参数指定一些特殊要求为0就是没有while(1){//循环接收打印数据if(msgrcv(msgid,rbuf,sizeof(rbuf)-sizeof(long),0,0) 0){perror(msgrcv());exit(1);}printf(NAME %s\n,rbuf.name);printf(MATH %d\n,rbuf.math);printf(CHINESE %d\n,rbuf.chinese);}//销毁消息队列实例//第一个参数是要进行控制的消息队列实例//第二个参数是要进行的操作命令//第三个参数是第二个参数操作的传参这里没有写NULLmsgctl(msgid,IPC_RMID,NULL);exit(0); } sender.c: #include stdio.h #include stdlib.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include string.h#include proto.hint main(){key_t key;struct msg_st sbuf;//先拿到keykey ftok(KEYPATH,KEYPROJ);if(key 0){perror(ftok());exit(1);}//根据拿到的key获得消息队列实例即可//因为通信的双方只要有一方创建了消息队列即可//本程序中已经由接收方创建了所以这里写0表示没有特殊操作int msgid msgget(key,0);if(msgid 0){perror(msgget());exit(1);}//发送数据//先构造数据sbuf.mtype 1; //这个值大于0即可//这里注意C语言的语法要求//name是一个数组名是一块连续空间的起始位置//如果没有在一开始定义的时候就进行初始化赋值//那么后面再进行赋值时其将成为常量常量不能在赋值号的左边出现嗷//所以只能使用strcpy进行赋值strcpy(sbuf.name,Alan);sbuf.math rand()%100;sbuf.chinese rand()%100;if(msgsnd(msgid,sbuf,sizeof(sbuf)-sizeof(long),0) 0){perror(msgsnd());exit(1);}puts(ok!);exit(0); } 先运行接收方 再运行发送方 再查看接收方 可以看见已经接收到了发送过来的数据。 我们也可以不先运行接收方直接让发送方连发三次数据当接收方运行的时候就会一下子接收到三条信息因为消息队列中缓存的有数据只要去相同的消息队列实例中拿取数据即可。 信号量数组 信号量数组是一个由多个信号量组成的数据结构每个信号量都可以用来表示一个资源的使用情况。在Linux系统中信号量数组被广泛用于进程间通信和同步以及保护共享资源。 每个信号量都是一个计数器可以用来表示资源的可用数量。当一个进程需要使用共享资源时它需要先读取信号量的值。如果信号量的值大于0表示资源可用进程可以使用该资源。如果信号量的值为0表示资源不可用进程需要等待直到资源可用。 在Linux中信号量数组通常用于管理多个共享资源的情况。例如当多个进程需要访问同一个文件时可以使用信号量数组来保护文件的访问权限。当一个进程正在访问文件时其他进程需要等待该进程释放资源后才能访问文件。这样可以避免多个进程同时访问同一个文件从而防止文件损坏或数据不一致的问题。 需要注意的是在Linux中信号量数组的操作是原子操作即它们是线程安全的。这意味着在多个进程同时访问信号量数组时不会出现竞争条件或死锁的情况。 semget() semget函数是Linux系统调用的一部分用于获取或创建一个信号量。信号量是一种同步机制用于解决多进程之间的同步和协调问题。 函数原型如下 #include sys/ipc.h int semget(key_t key, int nsems, int semflg);semget函数的参数包括 key一个由ftok函数生成的键值用于标识信号量集。如果这个键值是0那么semget将创建一个新的信号量集。 nsems指定信号量集中的信号量数量。通常这个值被设置为1表示只创建一个单一的信号量。 semflg标志位用于控制semget的行为。最常用的标志是IPC_CRE它告诉semget如果信号量集不存在则创建一个新的信号量集。 函数的返回值是一个指向信号量集的标识符即信号量集的ID如果函数执行失败将返回-1。 在使用semget函数时需要注意以下几点 信号量是进程间通信的一种方式因此需要谨慎地使用避免在多个进程之间造成混乱。 信号量集的创建和使用都需要使用适当的权限。一般来说只有具有适当权限的用户或进程才能创建和使用信号量集。 信号量是有限制的因此在使用时需要了解其限制例如最大数量和最大值等。 信号量集在使用完毕后需要使用semctl函数来释放和删除。 总之semget函数用于获取或创建信号量集它是Linux下进程间通信的一种机制可以用于解决多进程之间的同步和协调问题。 semop() semop函数是Linux系统下用于操作信号量的函数之一。信号量是一种用于进程间同步的机制通过它可以协调多个进程之间的访问和修改共享资源。 semop函数的原型如下 #include sys/ipc.h #include sys/sem.h int semop(int semid, struct sembuf *sops, size_t nsops);参数说明 semid信号量集的唯一标识符通常通过semget函数获取。 sops指向一个sembuf结构体的指针该结构体定义了要执行的操作。sembuf结构体包含三个成员 sem_num指定要操作的信号量在信号量集中的编号从0开始。 sem_op指定要执行的操作。正值表示要增加信号量的值负值表示要减少信号量的值。如果信号量的当前值小于要减少的值则操作将阻塞直到信号量的值足够大。 sem_flg指定操作的标志位。常用的标志包括IPC_NOWAIT非阻塞操作和SEM_UNDO在操作完成后自动撤销对信号量的改变。 nsops指定要执行的操作的数量即sops数组中结构体的数量。 返回值如果函数执行成功返回0如果执行失败返回-1并设置相应的错误码。 使用semop函数时需要注意以下几点 在调用semop之前需要先通过semget函数获取信号量集的标识符。 要确保对信号量的操作是原子的即在一个进程执行操作期间其他进程不能对该信号量进行操作。这可以通过设置合适的标志位或使用信号量相关的函数如sem_wait和sem_post来实现。 要注意信号量的初始化和释放。在使用完信号量后应该使用semctl函数释放相关的资源。 要注意错误处理。在调用semop函数后应该检查返回值以确定操作是否成功并根据需要处理错误情况。 总之semop函数是Linux系统下用于操作信号量的重要函数之一它可以用于实现进程间的同步和协调。通过合理地使用信号量可以有效地解决并发访问共享资源时的竞争条件问题。 semctl() semctl函数是Linux系统下的一个系统调用函数用于控制信号量集。信号量集是一种用于管理进程间同步和互斥的数据结构。 函数原型如下 #include sys/ipc.h #include sys/sem.h int semctl(int semid, int semnum, int cmd, union semun arg);参数说明 semid信号量集的唯一标识符通常通过semget函数获取。 semnum指定要操作的信号量在信号量集中的编号从0开始。 cmd指定要执行的操作命令。常见的命令包括 ——GETVAL获取信号量的当前值。 ——SETVAL将信号量的值设置为指定值。 ——GETPID获取前一个对此信号进行操作的进程的标识符。 ——GETNCNT等待信号值增加的进程的总数。 ——GETZCNT等待信号值变为0的进程的总数。 ——SETALL将所有semun结构中的值设定到信号集中。 arg根据命令的不同可以是一个不同的参数结构体。例如当命令为SETVAL时需要传递一个包含要设置的值的长整型参数结构体。当命令为GETALL时需要传递一个用于存储所有信号值的数组的指针。 返回值如果函数执行成功返回0如果执行失败返回-1并设置相应的错误码。 使用semctl函数时需要注意以下几点 在调用semctl之前需要先通过semget函数获取信号量集的标识符。 要确保对信号量的操作是原子的即在一个进程执行操作期间其他进程不能对该信号量进行操作。这可以通过设置合适的标志位或使用信号量相关的函数如sem_wait和sem_post来实现。 要注意信号量的初始化和释放。在使用完信号量后应该使用semctl函数释放相关的资源。 要注意错误处理。在调用semctl函数后应该检查返回值以确定操作是否成功并根据需要处理错误情况。 总之semctl函数是Linux系统下用于控制信号量的函数之一它可以用于获取和设置信号量的值、获取和设置进程信息等操作。通过合理地使用信号量可以有效地管理进程间的同步和互斥行为。 共享内存 共享内存Shared Memory是Linux下进程间通信Inter-process Communication, IPC的一种方式它允许多个进程共享一段物理内存以实现快速的数据交换和协同工作。 在Linux系统中每个进程都有自己的虚拟地址空间通过地址映射机制将虚拟地址转换为物理内存的地址。共享内存就是将一段物理内存区域定义为共享区域多个进程可以将其虚拟地址空间映射到这个共享区域从而可以访问和修改共享区域的数据。 共享内存的创建和管理由操作系统完成。当一个进程需要使用共享内存时它会向操作系统请求并获得一段共享内存然后将其映射到自己的虚拟地址空间中。其他进程也可以将共享内存映射到自己的虚拟地址空间从而可以访问和修改共享内存中的数据。 共享内存的优点在于其访问速度非常快因为通信时可以直接访问内存。相较于管道等其他IPC方式共享内存避免了数据在用户空间和内核空间之间的复制和拷贝提高了数据传输的效率。但是共享内存也存在一些缺点例如不支持阻塞等待操作可能会导致死锁等问题。此外共享内存的使用也需要谨慎因为多个进程可以同时访问和修改共享区域的数据需要有一定的数据同步和互斥机制来保证数据的正确性和一致性。 总之共享内存是一种高效的进程间通信方式适用于需要快速、高效地交换大量数据的场景如数据库、消息队列等应用中。在使用共享内存时需要注意数据的同步和互斥问题避免出现死锁和数据不一致等问题。 shmget() shmget函数是Linux系统下用于创建或获取共享内存段的函数。共享内存是一种进程间通信机制它允许多个进程共享同一段物理内存以实现快速的数据交换和协同工作。 函数原型如下 #include sys/ipc.h #include sys/shm.h int shmget(key_t key, size_t size, int shmflg);参数说明 key指定共享内存段的键值通常由ftok函数生成。 size指定共享内存段的大小以字节为单位。 shmflg指定共享内存段的标志位包括如下选项 ——IPC_CREAT如果指定的键值不存在则创建共享内存段。 ——IPC_EXCL如果指定了IPC_CREAT并且指定的键值已经存在则返回错误。 ——0指定共享内存段的权限位例如0600表示只有所有者可以读写。 返回值如果函数执行成功返回共享内存段的标识符即共享内存段的ID如果执行失败返回-1并设置相应的错误码。 使用shmget函数时需要注意以下几点 共享内存段的生命周期与进程无关当最后一个引用该共享内存段的进程退出时共享内存段将被自动删除。因此在使用完共享内存段后应该通过shmdt函数将其从当前进程的地址空间中解除映射。 共享内存段的访问权限由其标志位指定可以通过修改标志位来控制对共享内存段的访问权限。例如可以通过设置0600来限制只有所有者可以读写共享内存段。 在使用共享内存段时需要确保多个进程之间的同步和互斥以避免出现竞争条件和死锁等问题。可以通过信号量或其他同步机制来实现进程之间的同步和互斥。 共享内存段的大小受限于系统的限制和可用内存资源。因此在使用时需要注意合理地分配和管理内存资源。 总之shmget函数是Linux系统下用于创建或获取共享内存段的函数它提供了高效的进程间通信机制适用于需要快速、高效地交换大量数据的场景如数据库、消息队列等应用中。在使用时需要注意同步和互斥问题以及合理地分配和管理内存资源。 shmop() 注意这个使用man手册来查的时候必须用man shmop的方式来查询用man shmat是没有用的。 Linux系统下并没有shmop函数而是使用shmat函数来实现共享内存的映射。shmat函数用于将共享内存段映射到调用进程的地址空间中使得进程可以通过指针访问共享内存中的数据。 shmat函数的原型如下 #include sys/ipc.h #include sys/shm.h int shmat(int shmid, const void *shmaddr, int shmflg);参数说明 shmid指定共享内存段的标识符即通过shmget函数获取的标识符。 shmaddr指定共享内存段的地址如果为NULL则由系统自动分配地址。 shmflg指定共享内存的访问权限和附加标志。 返回值如果函数执行成功返回一个指向映射区域的指针如果执行失败返回-1并设置errno来指示具体的错误原因。 使用shmat函数时需要注意以下几点 调用进程必须具有足够的权限才能访问共享内存段。 映射区域的大小必须与共享内存段的大小相匹配否则会导致访问越界。 当进程不再需要访问共享内存时需要使用shmdt函数将映射区域解除映射以释放资源。 在多进程环境下需要注意同步和互斥问题以避免数据竞争和不一致性的情况发生。 总之shmat函数是Linux系统下用于将共享内存映射到进程地址空间的函数之一通过映射操作进程可以通过指针访问共享内存中的数据实现进程间的数据共享和通信。 除了上述这个函数还有一个函数shmdt shmdt函数是Linux系统下用于将共享内存段从当前进程的地址空间中解除映射的函数。它的原型如下 #include sys/types.h #include sys/shm.h int shmdt(const void *shmaddr);参数说明 shmaddr一个指向共享内存段的指针该指针通常是由shmat函数返回的地址。 返回值如果函数执行成功返回0如果执行失败返回-1并设置errno来指示具体的错误原因。 shmdt函数的作用是将共享内存段从当前进程的地址空间中分离相当于shmat函数的反操作。当进程不再需要访问共享内存段时可以调用shmdt函数将其解除映射以释放相应的资源。 需要注意的是shmdt函数仅仅是将共享内存段从当前进程的地址空间中分离并不会销毁共享内存段本身。共享内存段仍然存在于系统中直到显式删除或系统重启。 在使用shmdt函数时需要注意确保进程不再需要访问共享内存段以免出现意外的问题。同时在多进程环境下需要注意同步和互斥问题以避免数据竞争和不一致性的情况发生。 shmctl() shmctl函数是Linux系统下用于控制共享内存段的函数。通过shmctl函数我们可以执行各种操作来控制共享内存段包括删除共享内存段、修改共享内存段的属性等。 函数原型如下 #include sys/ipc.h #include sys/shm.h int shmctl(int shmid, int cmd, struct shmid_ds *buf);参数说明 shmid指定共享内存段的ID即通过shmget函数获取的标识符。 cmd指定要执行的控制命令用于指定要执行的操作比如删除共享内存段、修改权限等。常用的命令包括IPC_RMID删除共享内存段和IPC_SET修改共享内存段的属性等。 buf指向一个shmid_ds结构体的指针用于存储共享内存段的信息。可以为NULL表示不获取共享内存段的信息。 返回值如果函数执行成功返回值为0如果出现错误返回值为-1并设置errno来指示具体的错误原因。 shmctl函数可以执行的控制命令包括 IPC_RMID删除共享内存段。当使用完共享内存段后应该通过shmctl函数将其删除以释放内存资源。执行该命令时需要将buf参数设置为NULL。 IPC_SET修改共享内存段的属性。可以通过该命令来修改共享内存段的标志位、拥有者和权限等属性。执行该命令时需要将buf参数指向一个shmid_ds结构体并设置相应的字段来修改共享内存段的属性。 IPC_STAT获取共享内存段的属性。可以通过该命令来获取共享内存段的详细信息包括创建时间、最后一次修改时间、访问时间等。执行该命令时需要将buf参数指向一个shmid_ds结构体并获取共享内存段的信息。 使用shmctl函数时需要注意以下几点 在删除共享内存段时需要注意确保没有任何进程正在使用该共享内存段否则会导致删除失败。 在修改共享内存段的属性时需要注意权限问题。只有具有相应权限的进程才能修改共享内存段的属性。 在使用完共享内存段后需要通过shmdt函数将其从当前进程的地址空间中解除映射以释放共享内存段所占用的资源。 在多进程环境下需要注意同步和互斥问题以避免出现竞争条件和死锁等问题。可以通过信号量或其他同步机制来实现进程之间的同步和互斥。 实例 #include stdio.h #include stdlib.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include string.h #include sys/wait.h #include unistd.h#define MEMSIZE 1024int main(){pid_t pid;int shmid;//拿到相同的共享内存的key值//但这里因为是父子进程之间//所以不需要使用ftok来保证多个进程之间使用的是相同//的共享内存实例//ftok();//首先创建一个共享内存的实例//第一个参数表示共享内存实例的key值这里没有所以我们用IPC_PRIVATE表示是匿名实例//第二个参数是要设置的共享内存大小//第三个参数表示设置共享内存实例的权限shmid shmget(IPC_PRIVATE,MEMSIZE,0600);if(shmid 0){perror(shmget());exit(1);}//使用父子进程来实现共享内存的使用pid fork();if(pid 0){perror(fork());exit(1);}if(pid 0){ //子进程写 共享内存数据//使用shmat来映射这块共享内存实例到程序中来//第一个参数是共享内存实例的id号//第二个参数是映射到哪儿去为NULL表示由系统自动分配//第三个参数是设置一些特殊要求为0表示没有void* ptr shmat(shmid,NULL,0);if(ptr (void *)-1){//手册上是这么写的就按照手册写perror(shmat());exit(1);}//映射上来之后就可以往映射到的共享内存实例内开始写数据strcpy(ptr,Hello!);//用完就解除映射shmdt(ptr);exit(0);}else{ //父进程读 共享内存数据//收尸wait(NULL);void* ptr shmat(shmid,NULL,0);if(ptr (void *)-1){perror(shmat());exit(1);}puts(ptr);//解除映射shmdt(ptr);//销毁共享内存实例shmctl(shmid,IPC_RMID,NULL);exit(0);}exit(0); } 编译运行
http://www.zqtcl.cn/news/770562/

相关文章:

  • 西安阿里云网站建设一建报名资格条件
  • 聊城网站优化wordpress循环该分类子分类
  • 帮网站做关键词排名优化创造网站需要多少钱
  • 广西网站建设推荐wordpress 宣布停止
  • 专注网站制作青岛景观设计公司排名
  • 安庆做网站网站代理建设网站观澜
  • 网站开发需求收集 模板cms做门户网站
  • dw网站首页的导航怎么做有大佬给个网址吗
  • 一个网站怎么做聚合洛可可设计公司贾伟
  • 什么是优化型网站网页设计作业在线网站首页
  • 关于网站建设广告词英文案例网站
  • 有哪些可以做策划方案的网站国家域名
  • vk网站做婚介做seo排名好的网站
  • 广州企业网站建设公司苏州建网站提
  • html如何做购物网站天元建设集团有限公司法人代表
  • 教育培训机构排名seo是搜索引擎营销
  • 做奢侈品网站有哪些沧州手机建站哪家好
  • 德州网站网站建设广西房管局官网
  • 白石桥做网站公司seo顾问服务四川
  • 网站建设注册哪类商标十大网页设计公司
  • 网站建设的源代码有什么作用金华网站建设优化技术
  • 个人网站申请做瞹瞹嗳视频网站在线观看
  • 做网站 融资玉石网站建设的定位
  • 自己做的网站字体变成方框seo同行网站
  • 宁波网站建设培训微信小程序开发平台官网
  • 西部数码做的网站打不开哈尔滨模板建站推荐
  • 外贸网站建设流程杭州软件定制开发
  • 网站的首页面设计软文推广特点
  • 网站描述在哪里写网页设计图片怎么换
  • 深圳网站关键词优化推广做mod游戏下载网站