尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Liunx多任务-IPC机制

Liunx多任务-IPC机制 一.无名管道无名管道只能用在具有亲缘关系的进程间通信父子进程操作流程:1.创建并打开管道:pipe();2.读管道:read();3.写管道:write();4.关闭管道:close();int pipe(int pipefd[2]);功能:在内核区创建并打开一个无名管道即缓冲区父子共用内核区在创建父子进程之前否则在内核区创建两个独立管道参数:pipefd:管道读端和写端的文件描述符pipefd[0] 读端pipefd[1] 写端返回值:成功:0失败:-1管道的特点:管道本质是内核中的一段缓冲区默认64K字节遵循队列存储方式(FIFO)数据在管道中被读取后会自动从内核缓冲区中移除出队。1.写阻塞当管道的读写端都存在时管道写满数据时发生写阻塞。2.读阻塞当管道的读写端都存在时管道为空时读管道发生读阻塞。3.读返回0当管道没有写端closepipefd[1])只有读端时管道中有数据则读出数据无数据时不再读阻塞读管道直接返回0字节。4.管道破裂当管道没有读端(closepipefd[2])向管道中写数据发生管道破裂异常。二.有名管道有名管道可以用在同一主机任意进程间通信1.创建有名管道文件:mkfifo;int ret mkfifo(myfifo2,0664); if(ret -1 errno ! EEXIST) { perror(mkfifo2 error); return NULL; }2.打开管道文件:open;int fd open(myfifo2,O_WRONLY); if(fd -1) { perror(open error); return NULL; }3.写管道文件:write:4.读管道文件:read;5.关闭管道文件:close;三.信号信号进程间通知机制不携带数据--异步通信信号软中断1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN1 36) SIGRTMIN2 37) SIGRTMIN338) SIGRTMIN4 39) SIGRTMIN5 40) SIGRTMIN6 41) SIGRTMIN7 42) SIGRTMIN843) SIGRTMIN9 44) SIGRTMIN10 45) SIGRTMIN11 46) SIGRTMIN1247) SIGRTMIN13 48) SIGRTMIN14 49) SIGRTMIN15 50) SIGRTMAX-1451) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-1055) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-659) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX2 SIGINT:ctrl c让一个进程被打断3 SIGQUIT:ctrl \让一个进程结束9 SIGKILL:强制让一个进程结束11SIGSEGV:让一个进程结束(段错误)13SIGPIPE:让一个进程结束(管道破裂)14SIGALRM:让一个进程结束(定时时间到达)17SIGCHLD:子进程结束时发送给父进程18SIGCONT:让停止态的进程继续执行19SIGSTOP:让运行态的进程进入停止态暂停强制停止20SIGTSTP:ctrl z 让进程进入暂停态后台进程来自终端的停止信号10 SIGUSR112 SIGUSR2专门预留给程序员使用的未定义信号。1.注册信号信号处理方式1.忽略不处理2.缺省按照操作系统默认方式处理3.捕获按照自定义方式处理sighandler_t signal(int signum, sighandler_t handler);功能注册一个信号参数signum 要注册的信号的编号handler对信号的处理方式SIG_IGN : 按忽略方式处理SIG_DFL 按照缺省方式处理自定义的函数按照捕获方式处理返回值成功handler失败SIG_ERR注意1. 如果信号不注册自动按照默认缺省方式处理大多数信号默认处理方式是结束一个进程。2. 信号尽量早注册。2.发送信号int kill(pid_t pid, int sig);功能给进程发送一个信号与signal注册信号搭配使用参数pid接收信号的进程sig信号的编号返回值成功0失败-13.pausevoid pause(void);功能挂起一个进程让进程进入休眠可以通过一个信号唤醒pause挂起的进程但是这个信号必须被捕获先注册。4.alarmunsigned int alarm(unsigned int seconds);功能定时若干秒之后发送一个SIGALRM的信号可以注册自定义实现方式pause与alarm实现sleep功能void handler(int signum) { printf(%d signal is coming ,end\n,signum); } void mysleep(int n) { signal(SIGALRM,handler); alarm(5); int cnt 4; while(cnt--) { printf(sleeping\n); sleep(1); } pause(); } //定时5秒闹钟后执行4秒的任务任务结束后陷入pause第五秒结束时alarm发送SIGALRM信号执行handler函数执行结束后pause返回。信号处理函数handler一定先执行然后 pause() 才返回。四.消息队列system V IPC对象消息队列与管道的区别1. 将进程间通信的数据封装成消息体发送2. 增加消息类型可以根据消息的类型设置数据的优先级。1. 获取IPC的key值ftok();2. 创建消息队列 msgget();3. 发送消息队列消息: msgsnd();4. 接收消息队列消息 :msgrcv();5. 删除消息队列 : msgctl();struct msgbuf { long mtype; /* message type, must be 0 */ char mtext[MSG_LEN]; /* message data */ }; //系统定义的消息体结构消息正文大小可自定义1.ftokkey_t ftok(const char *pathname, int proj_id);功能产生一个IPC对象key值参数pathname路径名proj_id项目id返回值成功key值失败-1key_t key ftok(., ?); if (-1 key) { perror(ftok error); return -1; } printf(key %#x\n, key);2.msggetint msgget(key_t key, int msgflg);功能根据key值创建一个消息队列如果存在返回消息队列ID参数key IPC key值msgflgIPC_CREAT|0664返回值成功消息队列ID失败-1int msgid msgget(key, IPC_CREAT|0664); if (-1 msgid) { perror(msgget error); return -1; } printf(msgid %d\n, msgid);3.msgsndint msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);功能发送消息队列的消息参数msqid消息队列IDmsgp要发送的消息体struct msgbuf {long mtype; /* message type, must be 0 */ 消息类型char mtext[1]; /* message data */ 消息正文};msgsz消息正文大小msgflg 标志位0默认方式发送返回值成功0失败-1while (1) { msg.mtype MSG_TYPE_CHAT; fgets(msg.mtext, MSG_LEN, stdin);//读取用LEN最大长度 int ret msgsnd(msgid, msg, strlen(msg.mtext), 0);//发送用实际读取的长度 if (-1 ret) { perror(msgsnd error); return -1; } }4.msgrcvssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);功能从消息队列中接收消息参数msqid消息队列IDmsgp 要接受的消息的存储位置msgsz消息正文的大小msgtyp消息类型msgflg标志位0默认方式阻塞方式返回值成功返回实际消息正文的大小失败-1while (1) { memset(msg, 0, sizeof(msg)); ssize_t ret msgrcv(msgid, msg, MSG_LEN, MSG_TYPE_CHAT, 0); if (-1 ret) { perror(msgrcv error); return -1; } printf(msg %s\n, msg.mtext); }5.msgctlint msgctl(int msqid, int cmd, struct msqid_ds *buf);功能操作IPC对象对应的消息队列参数msqid消息队列的idcmd操作方法IPC_STAT:获取状态操作IPC_SET: 设置IPC_RMID:删除操作bufIPC_RMID buff-》NULL返回值成功0失败-1msgctl(msgid, IPC_RMID, NULL);6.IPC对象命令ipcs -a查看系统中的IPC对象ipcrm -q msgidipcrm -Q msgkey删除消息队列ipcrm -m shmidipcrm -M shmkey删除共享内存五.共享内存共享内存进程间效率最高的通信方式利用内存映射技术避免了数据的反复拷贝1.获取IPC对象的key值:ftok();2.创建共享内存:shmget();3.共享内存和用户进程空间建立内存映射关系:shmat():4.向用户空间写入/读出数据:5.解除内存映射关系:shmdt();6.删除共享内存:shmctl();1.shmgetint shmget(key_t key, size_t size, int shmflg);功能创建共享内存并获得共享内存的id参数key IPC对象key值size共享内存的大小PAGE_SIZE4096字节整数倍shmflg IPC_CREAT | 0664返回值成功共享内存的ID失败-1int shmid shmget(key, 4096, IPC_CREAT | 0664); if (-1 shmid) { perror(shmget error); return -1; } printf(shmid %d\n, shmid);2.shmatvoid *shmat(int shmid, const void *shmaddr, int shmflg);功能建立共享内存和用户空间的内存映射参数shmid共享内存idshmaddr映射的用户空间首地址NULL 由操作系统选择用户空间并以返回值的方式返回空间首地址shmflg SHM_RDONLY :只读SHM_RDONLY 读写返回值成功映射的用户空间首地址失败void *-1void *pmem shmat(shmid, NULL, !SHM_RDONLY); if ((void *)-1 pmem) { perror(shmat error); return -1; }3.shmctlint shmctl(int shmid, int cmd, struct shmid_ds *buf);功能操作共享内存参数shmid共享内存idcmd操作指令IPC_RMID 删除操作buf NULL返回值成功0失败-1shmdt(pmem);//解除内存映射 shmctl(shmid, IPC_RMID, NULL);
返回列表