标签:
int signal(int sig,__sighandler_t handler); int func(int sig);
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 end
int kill(pid_t pid,int sig);參数 pid 指定了信号发送的对象进程。
int n=0;
void fun(int sig)
{
cout<<n++<<endl;
}
int main()
{
signal(SIGUSR1,fun);受到信号运行fun函数
pid_t pid;
pid=fork();
if(pid==0)
{
pid_t ppid=getppid();
for(int i=0;i<5;i++){kill(ppid,SIGUSR1);sleep(1);}//发送信号
}
else if(pid>0)
{
wait(NULL);
}
else
{
perror("fork Error!");
exit(1);
}
return 0;
}输出: 0 1 2 3 4
void fun(int sig)
{
cout<<"alarm 5"<<endl;
}
int main()
{
signal(SIGALRM,fun);
pid_t pid;
pid=fork();
if(pid==0)
{
pid_t ppid=getppid();
alarm(5);//设置定时器,在5秒时将发送超时信号,并终止子进程运行。
sleep(8);
}
else if(pid>0)
{
wait(NULL);
}
else
{
perror("fork Error!");
exit(1);
}
return 0;
}pause等待进程捕捉并处理信号。
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就可以。
#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);
}文件和记录锁定可分为咨询式锁定和强制锁定两种。
int lockf(int fd,int function,long size); function能够是下面取值: F_ULOCK:为一个先前锁定的区域解锁 F_LOCK:锁定一个区域,假设指定文件的相应区域已被其他进程锁定,那么 lockf 的调用进程将被堵塞直到该区域解锁。 F_TLOCK:測试并锁定一个区域,假设被測试的区域上了锁,lockf便会马上返回-1,出错返回码 errno 将为 EAGAIN. F_TEST:測试一个区域是否已经上锁。 參数 size 指明了从文件当前位置開始的一段连续锁定区域的长度,当 size 为 0 时,锁定记录将由当前位置一直扩展到文件尾。
#include <unistd.h>
int main()
{
int fd;
char buf[2]={'\0'};
if((fd=open("data",O_RDWR))<=0)
{
perror("Can't open");
exit(1);
}
if(lockf(fd,F_LOCK,0)!=-1)//堵塞直到成功加锁
{
int i=0;
while(i++<3)
{
lseek(fd,0,0);
read(fd,buf,1);
buf[0]+=1;
cout<<buf<<endl;
lseek(fd,0,0);
write(fd,buf,1);
}
ockf(fd,F_ULOCK,0);
}
close(fd);
return(0);
}连续运行两次输出start 2 3 4 start 5 6 7假设改为F_TLOCK,则仅仅有第一个进程的输出.第二个进程没有输出.
int flock(int fd,int operation); 调用 flock 有两个參数: fd:一个已打开文件的文件描写叙述符; operation能够是下面取值: LOCK_SH:共享锁 LOCK_EX:相互排斥锁 LOCK_UN:解锁 LOCK_NB:当文件已被锁定时不堵塞
#include <sys/file.h>
int main()
{
int fd;
char buf[2]={'\0'};
if((fd=open("data",O_RDWR))<=0)
{
perror("Can't open");
exit(1);
}
if(flock(fd,LOCK_EX)!=-1)//设置堵塞性相互排斥锁
{
int i=0;
while(i++<3)
{
lseek(fd,0,0);
read(fd,buf,1);
buf[0]+=1;
cout<<buf<<endl;
lseek(fd,0,0);
write(fd,buf,1);
}
flock(fd,F_ULOCK);
}
close(fd);
return(0);
}start 2 3 4 start 5 6 7假设是LOCK_EX | LOCK_NB,则仅仅有第一个进程的输出.第二个进程没有输出.
key_t ftok(char *pathname,char proj);获取一个消息队列的标识符。
假设是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来取代。假设两个进程没有不论什么关系,就用ftok()。
int msgget(key_t key,int msgflg)创建新的消息队列或获取已有的消息队列。
int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg)msqid 是消息队列对象的标识符.
int msgctl(int msgqid, int cmd, struct msqid_ds *buf)msgqid:消息队列对象的标识符。
发送消息:
#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);
}输出:hello
POSIX 标准
POSIX名字规则(即open函数第一个參数规则):
1、必须以‘/’开头
2、出去第一个‘/’外,不能有其它‘/’
mqd_t mq_open(const char * name,int flags,/*mode_t mode,struct mg_attr *attr */)name:即上面所说名字
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);发送接收消息,最后一个參数(非负整数)设定/获取此消息的优先级。
创建消息队列并发送消息
#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;
}
struct sembuf {
unsigned short sem_num;
short sem_op;
short sem_flg;
};
sem_num 成员为接受操作的信号量在信号量数组中的序号(数组下标)。
sem_op 成员定义了进行的操作(能够是正、负和零)。
sem_flg 是控制操作行为的标志。
假设 sem_op 是负值,就从指定的信号量中减去对应的值。
假设 sem_op 是正值,就在指定的信号量中加上对应的值。
假设 sem_op 是零,那么调用 semop()函数的进程就会被堵塞直到相应的信号量值为零。
int semget(key_t key, int nsems, int semflg);建立新的信号量对象或者获取已有对象的标识符。
IPC_EXCL:和IPC_CREAT一起使用(用”|”连接),保证所得的消息队列对象是新创建的而不是打开已有的对象。
int semop(int semid, struct sembuf *sops, unsigned nsops);改变信号量对象中各个信号量的状态。
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
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)获取内存对象信息
void *mmap(void* addr,size_t len,int prot,int flags,int fd,off_t offset);addr:通常为空指针,意为让内核自行决定内存地址
int munmap(void *addr,size_t len)删除共享内存
int msync(void *addr,size_t len,int flags);flags:取值例如以下:
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <semaphore.h>
using namespace std;
int main()
{
int zero=0;
//创建信号量
sem_t *semd=sem_open("in1",O_CREAT,S_IRUSR|S_IWUSR,1);
//创建共享内存区
int fd=shm_open("in",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
//初始化内存区为0
write(fd,&zero,sizeof(int));
//映射共享内存到对应地址空间
int *num=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
for(int i=0;i<5;i++)
{
sem_wait(semd);
cout<<(*num)++<<'\t';
sem_post(semd);
}
sem_close(semd);
return 0;
}
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <semaphore.h>
using namespace std;
int main()
{
int zero=0;
//打开信号量
sem_t *semd=sem_open("in1",0,S_IRUSR|S_IWUSR,1);
//打开共享内存区
int fd=shm_open("in",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
int *num=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
for(int i=0;i<5;i++)
{
sem_wait(semd);
cout<<(*num)++<<'\t';
sem_post(semd);
}
sem_close(semd);
sem_unlink("in1");
shm_unlink("in");
return 0;
}
int shmget(key_t key, int size, int shmflg);创建新的或取得已有的共享内存。
int shmat(int shmid, char *shmaddr, int shmflg);将shmget()函数得到的共享内存,映射到进程自己的内存空间内。
int shmctl(int shmqid, int cmd, struct shmid_ds *buf);cmd:
int shmdt(char *shmaddr);
断开共享内存映射
一个进程发送数据
#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)获取内存对象信息
标签:
原文地址:http://www.cnblogs.com/bhlsheji/p/4229391.html