sig 指明了所要处理的信号类型,handler是SIG_IGN,SIG_DFL或者返回值为整数的函数地址。 当运行了signal函数后,进程仅仅要接收到类型为sig 的信号,就马上运行 func()函数,无论其正在运行程序的哪一部分。当func()函数运行结束后,程序返回到进程被中断的那一点继续运行。
忽略中止信号:
#include <signal.h> int main() { signal(SIGINT,SIG_IGN); /*告诉进程将 SIGINT 信号忽略*/ cout<<"start"<<endl; sleep(3); /*在此期间,无法中止程序执行*/ cout<<"end"<<endl; return 0; } 捕捉中止信号: void fun(int sig) { cout<<endl; cout<<"ctrl-c"<<endl; } int main() { signal(SIGINT,fun); /*告诉进程将 SIGINT 信号忽略*/ cout<<"start"<<endl; sleep(3); /*中止程序执行时,调用fun函数*/ cout<<"end"<<endl; return 0; } 输出: start ^C ctrl-c endpause等待进程捕捉并处理信号。
void fun(int sig){} int main() { signal(SIGALRM,fun); alarm(1); pause();//处于等待状态。 return 0; }++++++++++++++++++管道++++++++++++++++++
实现父子进程间的通信
fd用于存放 pipe()函数新建立的管道句柄
fd[0]是从管道中读出数据的句柄
fd[1]是向管道写入数据的句柄。即fd[1]的写入由 fd[0]读出。
int main() { int fd[2]; char buf[100]={'\0'}; pid_t pid; pipe(fd);//建立管道 pid=fork();//建立子进程 if(pid>0) { close(fd[1]);//关闭不须要的句柄 read(fd[0],buf,100); cout<<buf<<endl; } else if(pid==0) { close(fd[0]);//关闭不须要的句柄 strcpy(buf,"hello"); write(fd[1],buf,100); } else {exit(1);} return 0; }int dup(int oldfd);
将管道句柄重定向到标准输入/输出上最小的未使用的句柄. 在使用dup函数前最好将原句柄关闭.
int main() { int fd[2]; char buf[100]; char tmp[100]; pid_t pid; pipe(fd); pid=fork(); if(pid>0) { close(fd[1]); close(0);//关闭标准输入,0句柄是最小未使用句柄. dup(fd[0]); cin>>buf; cout<<buf<<endl; } else if(pid==0) { close(fd[0]); close(1);//关闭标准输出,1句柄是最小未使用句柄. dup(fd[1]); strcpy(tmp,"hello"); cout<<tmp<<endl; } else {exit(1);} return 0; }dup2函数相当于 close(0); dup(fd[0]); 这两条语句.
int main() { int fd[2]; char buf[100]={'\0'}; char tmp[100]={'\0'}; pid_t pid; pipe(fd); pid=fork(); if(pid>0) { close(fd[1]); dup2(fd[0],0); cin>>buf;//从管道读入 cout<<buf<<endl; } else if(pid==0) { close(fd[0]); dup2(fd[1],1); strcpy(tmp,"hello"); cout<<tmp<<endl;//读出到管道 } else {exit(1);} return 0; }FILE *popen(char *command,char *type); int pclose(FILE *stream);
popen()函数首先调用 pipe()函数建立一个管道,然后用 fork()函数建立一个子进程,执行一个 shell 环境,然后在这个 shell 环境中执行"command"參数指定的程序。数据在管道中流向由"type"參数控制。这个參数能够是"r"或者"w",分别代表读和写。
int main() { FILE *pipe_fp; if((pipe_fp = popen("ps -ef","r"))== NULL)//设置一个管道读. { perror("popen"); exit(1); } char buf[100]={'\0'}; fread(buf,1,99,pipe_fp);//从管道中读. cout<<buf<<endl; /* 关闭管道 */ pclose(pipe_fp); return(0); }解决管道不能提供非父/子关系进程间通信的缺陷. 在读取数据时,若管道中没有数据,有名管道会自己主动堵塞直到读取到数据为止.
int mknod(char *pathname,mode_t mode,dev_t dev); pathname:要创建的文件的名称; mode:文件类型; dev:该文件相应的设备文件的设备号。仅仅有当文件类型为 S_IFCHR 或 S_IFBLK 的时候该文件才有设备号,创建普通文件时传入0就可以。例如以下:S_IFIFO表示要创建一个FIFO文件,0666表示该文件的权限是全部人可读可写,0表示该文件不是一个设备文件。 管道读 #include <sys/stat.h> #include <unistd.h> int main() { char buf[100]={'\0'}; mknod("./tmpss",S_IFIFO|0666,0); FILE *fp=fopen("./tmpss","r"); fgets(buf,100,fp);//堵塞等待读取数据 fclose(fp); cout<<buf<<endl; return(0); } 管道写. int main() { FILE *fp = fopen("./tmpss","w") fputs("hello",fp); fclose(fp); return(0); }
文件和记录锁定可分为咨询式锁定和强制锁定两种。
key_t ftok(char *pathname,char proj);获取一个消息队列的标识符。 pathname和proj能够任意指定,不同的<pathname,proj>产生不同的标识符.收发消息两方应使用同样的<pathname,proj>.
假设是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来取代。假设两个进程没有不论什么关系,就用ftok()。
int msgget(key_t key,int msgflg) 创建新的消息队列或获取已有的消息队列。 key:消息队列对象的keyword(key). msgflg能够是下面取值: IPC_CREAT:假设消息队列对象不存在,则创建,否则进行打开操作; IPC_EXCL:和IPC_CREAT一起使用(用”|”连接),保证所得的消息队列对象是新创建的而不是打开已有的对象。 int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg) msqid 是消息队列对象的标识符. msgp 指向要发送的消息所在的内存. msgsz 是要发送信息的长度(字节数),能够用公式计算:msgsz = sizeof(struct mymsgbuf)- sizeof(long); msgflg能够是下面取值: 0,忽略标志位; IPC_NOWAIT,假设消息队列已满,消息将不被写入队列,马上返回。假设不指定这个參数,线程将被堵塞直到消息被能够被写入。int msgctl(int msgqid, int cmd, struct msqid_ds *buf) msgqid:消息队列对象的标识符。 cmd能够是下面取值: IPC_STAT:取出系统保存的消息队列的 msqid_ds 数据,并将其存入參数 buf 指向的 msqid_ds 结构中。 IPC_SET:设定消息队列的 msqid_ds 数据中的 msg_perm 成员。设定的值由 buf 指向的 msqid_ds结构给出。 IPC_EMID:将队列从系统内核中删除。
发送消息:
#include <sys/msg.h> struct mymsgbuf { long msgtype; char msgtext[100]={'\0'}; }; int main() { mymsgbuf buf; buf.msgtype=1; strcpy(buf.msgtext,"hello"); key_t key = ftok(".",'a'); int msgqueue_id = msgget(key, IPC_CREAT|IPC_EXCL|0660); msgsnd(msgqueue_id,(mymsgbuf*)&buf,sizeof(buf.msgtext),0); return(0); } 接受消息: struct mymsgbuf { long msgtype; char msgtext[100]={'\0'}; }; int main() { mymsgbuf buf; key_t key = ftok(".",'a'); int msgqueue_id = msgget(key, IPC_CREAT|0660); msgrcv(msgqueue_id,(mymsgbuf*)&buf,100,1,0); msgctl(msgqueue_id, IPC_RMID, 0); cout<<buf.msgtext<<endl; return(0); }输出: helloPOSIX 标准
POSIX名字规则(即open函数第一个參数规则): 1、必须以‘/’开头 2、出去第一个‘/’外,不能有其它‘/’
mqd_t mq_open(const char * name,int flags,/*mode_t mode,struct mg_attr *attr */) name:即上面所说名字 flags: 打开消息队列的权限 mode: 创建消息队列时的权限 attr:创建消息队列打属性 成功返回消息队列描写叙述符,失败返回-1 int mq_close(mqd_t mqd) 成功返回0,失败返回-1 关闭消息队列,(没有删除) int mq_unlink(mqd_t mqd) 删除此消息队列名,而消息队列在引用计数为0时销毁 int mq_getattr(mqd_t mqd,struct mq_attr *attr); int mq_setattr(mqd_t mqd,struct mq_attr *attr,struct mq_attr *oattr); 成功返回0,失败返回-1 分别时获取所指消息队列的属性 struct mqd_attr { long mq_flags; 0或者O_NONBLOCK long mq_maxmsg; 最大消息数 long mq_msgsize;每条消息最大size long mq_curmsgs;当前队列消息数 }; mq_send(mqd_t mqd,const char * buf,size_t len,unsigned int pro); mq_receive(mqd_t mqd,char * buf,size_t len,unsigned int *pro); 发送接收消息,最后一个參数(非负整数)设定/获取此消息的优先级。 编译时须要指定对应函数库-lrt创建消息队列并发送消息
#include <iostream> #include <stdio.h> #include <errno.h> #include <mqueue.h> #include <unistd.h> using namespace std; int main() { freopen("in.txt","r",stdin); //消息队列属性 struct mq_attr attr; attr.mq_flags=1; attr.mq_maxmsg=5; attr.mq_msgsize=100; mqd_t mqd=mq_open("/mqd",O_WRONLY|O_CREAT,S_IWUSR|S_IRUSR,&attr); // mqd_t mqd=mq_open("mqd",O_WRONLY); //设置消息队列属性 attr.mq_flags=0; mq_setattr(mqd,&attr,NULL); char sendbuf[100]; //发送消息 fgets(sendbuf,100,stdin); mq_send(mqd,sendbuf,100,0); fgets(sendbuf,100,stdin); mq_send(mqd,sendbuf,100,0); fgets(sendbuf,100,stdin); mq_send(mqd,sendbuf,100,0); //关闭消息队列 mq_close(mqd); return 0; }
接收消息并删除消息队列
#include <iostream> #include <mqueue.h> #include <unistd.h> #include <fcntl.h> using namespace std; int main() { struct mq_attr attr; //仅仅读打开消息队列 mqd_t mqd=mq_open("/mqd",O_RDONLY); mq_getattr(mqd,&attr); int bufsize=attr.mq_msgsize; //接收消息的buf必须大于等于消息队列设定的每一条消息大小 char recvbuf[bufsize]; int recv_len=0; while(attr.mq_curmsgs>0) { recv_len=mq_receive(mqd,recvbuf,bufsize,NULL); if(recv_len>=0) { cout<<recvbuf<<endl; mq_getattr(mqd,&attr); } else break; } //关闭并删除消息队列 mq_close(mqd); mq_unlink("mqd"); return 0; }
sem_num 成员为接受操作的信号量在信号量数组中的序号(数组下标)。
sem_op 成员定义了进行的操作(能够是正、负和零)。
sem_flg 是控制操作行为的标志。
假设 sem_op 是负值,就从指定的信号量中减去对应的值。
假设 sem_op 是正值,就在指定的信号量中加上对应的值。
假设 sem_op 是零,那么调用 semop()函数的进程就会被堵塞直到相应的信号量值为零。
int semget(key_t key, int nsems, int semflg); 建立新的信号量对象或者获取已有对象的标识符。 nsems:指定新生成的信号量对象中信号量的数目。 key:消息队列对象的keyword(key). semflg能够是下面取值: IPC_CREAT:假设消息队列对象不存在,则创建,否则进行打开操作;IPC_EXCL:和IPC_CREAT一起使用(用”|”连接),保证所得的消息队列对象是新创建的而不是打开已有的对象。
int semop(int semid, struct sembuf *sops, unsigned nsops); 改变信号量对象中各个信号量的状态。 semid:信号量对象的标识符。 sops:sembuf数组,定义semop()函数所要进行的操作序列。nsops:sops数组的长度。
一个进程创建并使用信号量: #include <sys/sem.h> union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; int main() { key_t mykey = ftok(".",'b'); sembuf sops1{0,-1,0}; sembuf sops2{0,1,0}; semun semopts; semopts.val = 1; int sid = semget(mykey, 1, IPC_CREAT | 0660); semctl(sid, 0, SETVAL, semopts); semop(sid, &sops1,1); sleep(5); cout<<"do something"<<endl; semop(sid, &sops2,1); } 还有一个进程使用信号量: int main() { key_t mykey = ftok(".",'b'); sembuf sops1{0,-1,0}; sembuf sops2{0,1,0}; int sid = semget(mykey, 1, IPC_CREAT | 0660); semop(sid, &sops1,1); cout<<"another do something "<<endl; semop(sid, &sops2,1); semctl(sid, 0, IPC_RMID, 0); } 输出: do something another do something
断开共享内存映射
一个进程发送数据
#include <sys/shm.h> int main() { key_t mykey = ftok(".",'b'); int shmid = shmget(mykey, 100, IPC_CREAT|IPC_EXCL|0666); char *segptr = (char *)shmat(shmid, 0, 0); strcpy(segptr, "hello"); } 一个进程读取数据 int main() { key_t mykey = ftok(".",'b'); int shmid = shmget(mykey, 100, 0); char *segptr = (char *)shmat(shmid, 0, 0); cout<<segptr<<endl; shmctl(shmid, IPC_RMID, 0); } 输出: hello int shm_open(const char* name,int flags,mode_t mode); 成功返回非负描写叙述符失败返回-1 int shm_unlink(const chat * name); 成功返回0,失败-1 int ftruncate(int fd,off_t len); 改动内存区大小 int fstat(int fd,const stat *buf) 获取内存对象信息转载于:https://www.cnblogs.com/bhlsheji/p/4229391.html