【整理】linux进程间通信函数整理

来源:互联网 发布:nginx centos 重启 编辑:程序博客网 时间:2024/05/28 06:06
 /*****************************************************************************************************
 *
 *进程间通信 IPC
 *
 ******************************************************************************************************/
 
 
 *
 *
 *函数名 : ftok
 *
 *作用 : 系统建立IPC通讯 ( 消息队列、信号量和共享内存 ),时必须指定一个ID值 .
 * 通常情况下,该id值通过ftok函数得到。
 *
 *原型 : key_t ftok(char *fname, int id)
 *
 *fname : 你指定的文件 .
 *
 *id : 子序号 虽然为int,但是只有8个比特被使用(0-255)。.
 *
 *返回 : 成功 : key_t值被返回 ; 错误 : -1 ;
 *
 *
 
 
 
 
 *
 *
 *函数名 : semget(信号量)
 *
 *作用 : 它的作用是创建一个新信号量或取得一个已有信号量,原型为:
 *
 *原型 : int semget(key_t key, int num_sems, int sem_flags);  
 *
 *头文件 : #include <sys/sem.h>
 *
 *返回 : 信号标识符(非零) :   失败返回-1.
 *
 *第一个参数key是整数值(唯一非零),多个进程可以通过它访问同一个信号量,
 *其中有个特殊值IPC_PRIVATE用于创建当前进程的私有信号量。
 *
 *第二个参数num_sems指定需要的信号量数目,它的值几乎总是1。
 *
 *第三个参数sem_flags是一组标志,同open()权限位,可以用八进制标识;
 *当想要当信号量不存在时创建一个新的信号量,
 *可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,
 *也不会产生错误。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。
 *
 *
 
 
 
 *
 *
 *函数名 : semctl函数
 *
 *作用 : 该函数用来直接控制信号量信息,
 *
 *原型为 : int semctl(int sem_id, int sem_num, int command, ...);  
 *
 *返回 : 成功 : STAT SETVAL RMID : 0 , GETVAL : 信号量当前值 ; 出错 -1 ;
 *
 *如果有第四个参数,它通常是一个union semum结构,定义如下:
 *union semun{  
 *   int val;    //信号量初值
 *   struct semid_ds *buf;  
 *   unsigned short *arry;  
 * };  
 *
 *sem_num 信号量编号当使用信号集才会被用到,通常取  0  即单个信号量 . 
 *
 *command通常是下面两个值中的其中一个
 * 
 *SETVAL:用来把信号量初始化为一个已知的值。p 这个值通过union semun中的val成员设置,
 *其作用是在信号量第一次使用前对它进行设置。
 *
 *IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。
 *
 *
 *


 
 
 *
 *
 *函数 : semop   
 *
 *作用 : 改变信号量的值
 *
 *原型为 : int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);  
 *
 *返回 : 信号量标识符,在信号量的其他函数中会使用改值 ; 出错 : -1 ;
 *
 *sem_id : 由semget返回的信号量标识符,sembuf结构的定义如下:
 *
 * struct sembuf{  
 *   short sem_num;//除非使用一组信号量,否则它为0  
 *   short sem_op; //信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,  
 *                 //一个是+1,即V(发送信号)操作。  
 *   short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,  
 *                 //并在进程没有释放该信号量而终止时,操作系统释放信号量  
 * };
 *
 *nsops : 操作数组sops中的操作个数(元素数目) , 通常取值为 1 (一个操作) . 
 *
 *
 
 
 
 *
 *
 *函数 : semctl函数
 *
 *作用 : 该函数用来直接控制信号量信息,它的原型为
 *
 *原型 : int semctl(int sem_id, int sem_num, int command, ...);  
 *
 *如果有第四个参数,它通常是一个union semum结构,定义如下 :
 *union semun{  
 *   int val;  
 *   struct semid_ds *buf;  
 *   unsigned short *arry;  
 * };  
 *
 *前两个参数与前面一个函数中的一样,command通常是下面两个值中的其中一个
 *SETVAL:用来把信号量初始化为一个已知的值。p 这个值通过union semun中的val成员设置,
 *其作用是在信号量第一次使用前对它进行设置。
 *IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。
 *
 *
 
 
 *
 *
 *函数 : shmget
 *
 *作用 : 创建共享内存。也就是从内存中获得一段共享内存区域,这里用到的函数是shmget();
 *
 *函数名 : int shmget(key_t key,int size,int shmflg)
 *
 *#include<sys/types.h>   #include<sys/ipc.h>  #include<sys/shm.h>
 *
 *返回 : 成功 : 共享内核段标识符 ; 失败 : -1 ;
 *
 *key : 共享内存的键值, 这个进程可以通过它访问同一个共享内存,其中有个特殊值
 *IPC_PRIVATE,用于创建当前进程的私有共享内存 .
 *
 *size : 共享内存大小 .
 *
 *shmflg : 同open() 函数的权限位,也可以使用八进制表示法 .
 *
 *
 
 
 
 *
 *
 *函数 : shmat
 *
 *作用 : 映射共享内存。也就是把这段创建的共享内存映射到具体的进程空间中,这里使用的函数是shmat()。
 *到这一步就可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读写命令对其进行操作。
 *
 *函数名 : char *shmat(int shmid,const void *shmaddr,int shmflg)
 *
 *返回值 : 成功 : 被映射的共享内存的标识符 ; 失败 : -1 ;
 *
 *shmid : 要映射的共享内存标识符 .
 *
 *shmaddr : 将共享内存映射到指定地址,注意这里的是一个void型的指针(
 * 为0则表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)
 *shmflg : SHM_RDONLY : 共享内存只读.
 *   默认 0 : 共享内存可读写.
 *
 *
 *
 
 
 *
 *
 *函数名 : shmdt
 *
 *作用 : 撤销映射。使用完共享内存就需要撤销,用到的函数是shmdt()。
 *
 *int shmdt(const vpod *shmaddr)
 *shmaddr : 被映射的共享内存段地址
 *成功 : 0    , 出错  : -1 .
 *
 *
 
 *
 *
 *4管理共享内存shmctl
 *
 *函数原型:int  shmctl(int   shmid,    int   cmd,    struct   shmid_ds   *buf)
 *
 *管理共享没存。
 *
 *-----------------------------------------------
 *
 *shmid 共享内存标识符
 *cmd     IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf;
 *           IPC_SET:改变共享内存的状态,把shmid_ds中的uid、gid、mode复制到共享内存的shmid_ds结构体。
 *           IPC_RMID:删除这片共享内存
 *buf 共享内存管理结构体。具体说明参见贡献内存内核结构定义部分。
 *
 *返回值
 *
 *----------------------------------------------- 
 *
 *成功返回0
 *出错返回-1,错误原因存在于error中
 *
 *错误代码
 *
 *-----------------------------------------------
 *
 *EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存
 *EFAULT:参数buf指向无效的内存地址
 *EIDRM:标识符为msqid的共享内存已被删除
 *
 *EINVAL:无效的参数cmd或shmid
 *EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行
 *
 *
 *
 *
 
 
 
 *
 *函数名 : shmget(得到一个共享内存标识符或创建一个共享内存对象)
 *
 *所需头文件 :  #include <sys/ipc.h>  #include <sys/shm.h>
 *
 *函数说明 :得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符
 *
 *函数原型 :int shmget(key_t key, size_t size, int shmflg)
 *
 *函数传入值   :
 *      key    : 0 (IPC_PRIVATE):会建立新共享内存对象
 *               大于0的32位整数 : 视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值size大于0的整数:
 *    size   : 新建的共享内存大小,以字节为单位 ;  0:只获取共享内存时指定为0
 *      shmflg : 0:取共享内存标识符,若不存在则函数会报错
 *               IPC_CREAT : 当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存 ;
 *             如果存在这样的共享内存,返回此共享内存的标识符 .
 *                IPC_CREAT|IPC_EXCL : 如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错
 *
 *函数返回值    :成功:返回共享内存的标识符  ;  出错:-1,错误原因存于error中
 *
 *附加说明      :
 *上述shmflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限
 *
 *错误代码      :
 *EINVAL:参数size小于SHMMIN或大于SHMMAX
 *EEXIST:预建立key所指的共享内存,但已经存在
 *EIDRM:参数key所指的共享内存已经删除
 *ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)
 *ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位
 *EACCES:没有权限
 *ENOMEM:核心内存不足
 *








 *
 *函数名     : shmat(把共享内存区对象映射到调用进程的地址空间)
 *
 *所需头文件 : #include <sys/types.h> #include <sys/shm.h>
 *
 *函数说明   : 连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
 *
 *函数原型   : void *shmat(int shmid, const void *shmaddr, int shmflg)
 *
 *函数传入值 : shmid :共享内存标识符
 *          shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
 *            shmflg :SHM_RDONLY:为只读模式,其他为读写模式
 *
 *函数返回值 : 成功:附加好的共享内存地址 ; 出错:-1,错误原因存于errno中 ;
 *
 *附加说明   :fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地址自动脱离(detach)。
 *            进程结束后,已连接的共享内存地址会自动脱离(detach)
 *错误代码
 *EACCES:无权限以指定方式连接共享内存
 *EINVAL:无效的参数shmid或shmaddr
 *ENOMEM:核心内存不足
 *
 *




 *
 *
 *函数名 : msgget
 *
 *作用 : 创建或打开消息队列 .
 *
 *头文件 : #include<sys/types.h> #include <sys/ipc.h> #include<sys/msg.h>  
 *
 *函数原型 : int msgget(key_t key,int msgflg)
 *
 *key : 消息队列的键值 ,多个进程可通过他访问同一个消息队列,其中有个特殊值IPC_PRIVATE,
 *用于创建当前进程的私有消息队列 . 
 *
 *msgflg : 权限标志位
 *
 *成功 : 消息队列 ID
 *出错 : -1
 *
 *
 *




 *
 *
 *函数名 : msgsnd
 *
 *作用 : 添加消息 . 使用的函数是msgsnd() ,它把消息添加到已打开的消息队列末尾 .
 *
 *头文件 : #include<sys/types.h> #include <sys/ipc.h> #include<sys/msg.h>  
 *
 *原型 : int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg)
 *
 *msg : 消息队列的队列 ID.
 *
 *msgp : 指向消息结构的指针 , 该消息结构msgbuf 通常如下 .
 *
 * struct msgbuf
 * {
 * long mtype;  /*消息类型,该结构必须从这个域开始*/
 * char mtext[1]; /*消息正文 自定大小  应该是*/
 * }
 *
 *msgsz : 消息正文的字节数 (不包括消息类型指针变量)
 *
 *msgflg : IPC_NOWAIT : 若消息无法立即发送(如当前消息队列已满), 函数会立即返回0
 * 0 : msgsnd 调用阻塞直到发送成功为止 .
 *
 *
 
 
 
 *
 *
 *函数名 : msgrcv
 *
 *作用 : 读取消息。使用的函数是msgrcv(),它把消息从消息队列中取走,与FIFO不同的是,这里可以取走指定的某一条消息
 *
 *函数原型 : int msgrcv(int msqid,void *msgp,size_t msgsz,long int msgtyp,int msgflg)
 *
 *msqid : 消息队列ID
 *
 *msgp : 消息缓冲区,同 msgsnd 中的msgp .
 *
 *msgsz : 消息正文的字节数 .
 *
 *msgtyp : 0 :接收消息队列中第一个消息 ;大于 0 : 接收消息队列中第一个类型为msgtyp的消息
 *小于0 : 接收消息队列中第一个类型值 不小于msgtyp绝对值且类型值最小的消息 .
 *msgtyp 可以以非先进先出次序读消息.
 *
 *msgflg : IPC_NOWAIT 使操作不阻塞 , 如果没有指定类型的消息可用 ,则 msgrcv 返回 -1 .
 *
 *






 *
 *
 *函数 : msgctl 
 *
 *作用 :  控制消息队列。它可以完成多项功能。
 *
 *函数原型 : int msgctl(int msgqid,int cmd,struct msgid_ds *buf)
 *msqid : 消息队列 的 队列ID
 *
 *cmd : 命令参数 :IPC_STAT : 读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中
 *
 *IPC_SET : 设置消息队列的数据结构msqid_ds中的ipc_pem域(IPC操作权限描述结构)值 ,这个值取自buf参数
 *
 *IPC_RMID : 从系统内核中删除消息队列
 *
 *buf : 描述消息队列的 msqid_ds 结构类型变量
 *
 *成功 :  0  ;  出错 : -1 ;
 *
 *
 *
 
 




 *
 *函数名  : system
 *函数详解  (执行shell 命令)
 *
 *相关函数 :
 *fork,execve,waitpid,popen
 *
 *表头文件 :#include<stdlib.h>
 *
 *定义函数  :int system(const char * string);
 *
 *函数说明  :system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,
 *         此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
 *
 *返回值    : 失败 : 如果fork()失败 返回-1:出现错误 如果exec()失败,表示不能执行Shell,返回值相当于Shell执行了exit(127)
 *            成功 : 如果执行成功则返回子Shell的终止状态
 *
 *如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),仅当命令处理程序可用时,返回非零值,
 *可以通过这一特征判断在一个给定的操作系统上是否支持system函数(当system返回为0时,表明system函数无效,在UNIX系统中,system函数总是可用的) ;
 *如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,
 *因此最好能再检查errno 来确认执行成功。
 *
 *附加说明   :在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。
 * 
 *范例
 *#include<stdlib.h>
 *main()
 *{
 *system(“ls -al /etc/passwd /etc/shadow”);
 *} 
 *执行结果:
 *-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
 *-r--------- 1 root root 572 Sep 2 15 :34 /etc/shado 
 *例2:
 *char tmp[];
 *sprintf(tmp,"/bin/mount -t vfat %s /mnt/usb",dev);
 *system(tmp);
 *其中dev是/dev/sda1.
 *
 *与exec的区别
 *1、system()和exec()都可以执行进程外的命令,system是在原进程上开辟了一个新的进程,但是exec是用新进程(命令)覆盖了原有的进程
 *2、system()和exec()都有能产生返回值,system的返回值并不影响原有进程,但是exec的返回值影响了原进程
 *
 *
0 0
原创粉丝点击