#include
int pipe(int fd[2]); //成功返回0,失败返回-1
#include
#include
#include
#include
#include
#include
int main(){
int fd[2] = {0};
int pid;
int fp;
int status;
char wbuf[128] = "message from child";
char rbuf[128] = {0};
fp = pipe(fd);
pid = fork();
if(fp == -1){
printf("creat pipe fail\n");
exit(-1);
}else{
if(pid > 0){
wait(&status);
close(fd[1]);
read(fd[0],rbuf,strlen(wbuf));
printf("father:strlen(rbuf) = %ld\n",strlen(rbuf));
printf("father:read message\n");
printf("father:message = %s\n",rbuf);
printf("status = %d\n",WEXITSTATUS(status));
}else if(pid == 0){
close(fd[0]);
write(fd[1],wbuf,strlen(wbuf));
printf("child:strlen(wbuf) = %ld\n",strlen(wbuf));
printf("child:send message\n");
exit(0);
}else{
printf("fork error\n");
}
}
return 0;
}
child:strlen(wbuf) = 18
child:send message
father:strlen(rbuf) = 18
father:read message
father:message = message from child
status = 0
ztj@ubuntu:~
FIFO,也叫命名管道,它是一种文件类型
#include
#include
int mkfifo(const char *pathname, mode_t mode);
#include
#include
#include
#include
int main(){
if((mkfifo("./file",0600) == -1)&&(errno != EEXIST)){
printf("mkfifo failuer\n");
perror("why");
}
return 0;
}
ztj@ubuntu:~/part2/IPC$ ls
a.out demo1.c demo2.c demo3.c file
ztj@ubuntu:~/part2/IPC$ rm file
ztj@ubuntu:~/part2/IPC$ ls
a.out demo1.c demo2.c demo3.c
ztj@ubuntu:~/part2/IPC$ ./a.out
ztj@ubuntu:~/part2/IPC$ ls
a.out demo1.c demo2.c demo3.c file
ztj@ubuntu:~/part2/IPC$ ./a.out
#include
#include
#include
#include
#include
#include
int main(){
char buf[128] = {0};
int nread;
int fd = open("./file",O_RDONLY);
if(fd != 0){
printf("open success!!!\n");
}
while(1){
nread = read(fd,buf,128);
printf("read %d byte\n",nread);
sleep(1);
}
close(fd);
return 0;
}
#include
#include
#include
#include
#include
#include
int main(){
int fd;
int nwrite;
char buf[128] = "1232154874554654";
if((mkfifo("./file",0600) == -1)&&(errno != EEXIST)){
printf("mkfifo failuer\n");
perror("why");
}
fd = open("./file",O_WRONLY);
if(fd != -1){
printf("open success!!!\n");
}
while(1){
nwrite = write(fd,buf,128);
// printf("write %d byte\n",nwrite);
sleep(1);
}
close(fd)
return 0;
}
消息队列,是消息的链接表,存放在内核中,一个消息队列有一个标识符来标识
#include
#include
#include
- //创建或打开消息队列。成功返回队列ID,失败返回-1
- int msgget(key_t key, int msgflg);
- //添加消息,成功返回0,失败返回-1
- int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- //读取消息,成功返回数据长度,失败返回-1
- ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
- //控制消息队列,成功返回0,失败返回-1
- int msgctl(int msqid, int cmd, struct msqid_ds *buf);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
#include
#include
key_t ftok(const char *pathname, int proj_id);
#include
#include
#include
#include
#include
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main(){
key_t key;
key = ftok(".",'x');
printf("key = %x\n",key);
struct msgbuf readbuf;
struct msgbuf sendbuf = {888,"msg from msgSnd"};
//1.打开/创建消息队列 :int msgget(key_t key, int msgflg);
int msgId = msgget(key, IPC_CREAT|0777);
if(msgId == -1){
printf("get que failuer\n");
}
//2.发送消息:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgId, &sendbuf, strlen(sendbuf.mtext), 0);
printf("msgsnd:%s\n",sendbuf.mtext);
//3.接收消息: size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgrcv(msgId,&readbuf,sizeof(readbuf.mtext),998,0);
printf("msgget: %s\n",readbuf.mtext);
//4.移除队列 IPC_RMID int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgId, IPC_RMID, NULL);
return 0;
}
#include
#include
#include
#include
#include
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main(){
key_t key;
key = ftok(".",'x');
printf("key = %x\n",key);
struct msgbuf readbuf;
struct msgbuf sendbuf = {998,"msg from msgGet"};
//1.打开/创建消息队列 :int msgget(key_t key, int msgflg);
int msgId = msgget(key, IPC_CREAT|0777);
if(msgId == -1){
printf("get que failuer\n");
}
//2.接收消息: size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgrcv(msgId,&readbuf,sizeof(readbuf.mtext),888,0);
printf("msgget: %s\n",readbuf.mtext);
//3.发送消息:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgId, &sendbuf, strlen(sendbuf.mtext), 0);
printf("msgsnd:%s\n",sendbuf.mtext);
//4.移除队列 IPC_RMID int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgId, IPC_RMID, NULL);
return 0;
}
#include
#include
1.//创建或获取一个共享内存,成功返回共享内存id,失败返回-1;size大小与M对齐
2. int shmget(key_t key, size_t size, int shmflg);
3.//连接共享内存到当前地址空间,成功返回共享内存指针,失败返回-1;第二,三个参数一般写0;代表系统为共享内存自动安排系统空间和共享内存可读可写
4. void *shmat(int shmid, const void *shmaddr, int shmflg);
5.// 断开与共享内存的连接,成功返回0,失败返回-1
6. int shmdt(const void *shmaddr);
7. //控制共享内存的相关信息,成功返回0,失败返回-1
8. int shmctl(int shmid, int cmd, struct shmid_ds *buf);
#include
#include
#include
#include
#include
#include
#include
int main(){
int shmid;
char *shmaddr;
key_t key = ftok(".",1);
//创建或获取一个共享内存,成功返回共享内存id,失败返回-1
shmid = shmget(key, 1024*4, IPC_CREAT|0666);
if(shmid == -1){
printf("shmget failuer\n");
exit(-1);
}
//连接共享内存到当前地址空间,成功返回共享内存指针,失败返回-1;第二,三个参数一般写0
shmaddr = shmat(shmid, 0, 0);
strcpy(shmaddr,"曽铁江");
//sleep(5);//等待另一端读取,并写入
printf("%s\n",shmaddr);
// 断开与共享内存的连接,成功返回0,失败返回-1
shmdt(shmaddr);
//控制共享内存的相关信息,成功返回0,失败返回-1
shmctl(shmid, IPC_RMID, 0);
return 0;
}
ztj@ubuntu:~/part2/IPC$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
忽略:大多数可以用这种方式处理,除了SIGKILL和SIGSTOP,因为它们向内核与超级用户提供的进程终止的可靠方法,不能忽略。
捕捉信号:实际上用中断处理函数,当信号产生时,内核调用函数,实现信号处理
默认动作:对应于每个信号,系统都有默认的处理方式。可以使用man 7 signal 来查看
可以使用“kill -信号编号/信号名字 进程id ” 手动杀死一个进程,如:kill -9 4222
信号处理函数:
1.入门版:signal
2.高级版:sigaction
信号发送函数:
1.入门版:kill
2.高级版:sigqueue
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
#include
#include
int kill(pid_t pid, int sig);
#include
#include
void sighandler(int signum){
switch(signum){
case 9:
printf("SIGKILL\n");
break;
case 2:
printf("SIGINT\n");
break;
}
printf("never quit\n");
}
int main(){
signal(SIGINT,sighandler);
signal(SIGKILL, sighandler);
while(1);
return 0;
}
#include
#include
#include
#include
int main(int argc,char **argv){
int signum;//信号的编号
int pid;//目标进程的pid
char cmd[128] = {0};
signum =atoi(argv[1]);//注意:atoi 将字符转换为int型
pid =atoi(argv[2]);
sprintf(cmd,"kill -%d %d",signum,pid);//构造system()所需的参数
// kill(pid,signum);
system(cmd);//如果不用system,也可以直接用kill发送信号
return 0;
}
#include
int sigqueue(pid_t pid, int sig, const union sigval value);
#include
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
struct sigaction {
void (*sa_handler)(int); //信号处理程序,不接受额外数据,与signal的参数相同,一般默认设为SIG_IGN忽略
void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理程序(函数),接收额外数据
sigset_t sa_mask;//阻塞关键字的信号集,默认为阻塞
int sa_flags;//影响接收数据的行为,SA_SIGINFO表示能够接收数据,需要手动设置
void (*sa_restorer)(void);//不用于应用程序,不用管
};
sa_sigaction:
参数int:num,用于接收signum
参数siginfo_t*:结构体
参数void*:一个指针,当指针为空的时候表示无数据,非空表示有数据,用于判断
signfo_t:
内容1:pid,谁发的
内容2:si_int,整型数
内容3:si_value,也是一个含数据的联合体,支持int和char*数据
..........(具体man 手册查看)
#include
#include
void handler(int signum, siginfo_t *info, void *context ){
printf("get signum = %d\n",signum);
if(context != NULL){
printf("get data = %d\n",info->si_int);
printf("get data = %d\n",info->si_value.sival_int);
}
}
int main(){
int signum = 2;
struct sigaction act;
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
sigaction(signum,&act,NULL);
while(1);
return 0;
}
#include
#include
#include
/*union sigval {
int sival_int;
void *sival_ptr;
};*/
int main(int argc,char **argv){
int signum = atoi(argv[1]);
pid_t pid = atoi(argv[2]);
union sigval value;
value.sival_int = 123456789;
sigqueue(pid,signum, value);
return 0;
}
信号量和 IPC 的结构不同,它是一个计数器。用于实现进程间的同步和互斥,而不是存储进程间的通信数据
Linux信号量函数都是在信号量组上进行操作,而不是在单一的二值(0/1)信号量操作
#include
#include
#include
1.//创建和获取一个信号量组,成功返回信号量集ID,失败返回-1
2. int semget(key_t key, int nsems, int semflg);
3. //对信号量进行操作,改变信号量的值,成功返回0,失败返回-1
4. int semop(int semid, struct sembuf *sops, size_t nsops);
5. //控制信号量的相关信息,第二个参数为:第几个信号量(0开始)
6. int semctl(int semid, int semnum, int cmd, ...);
union semun {
int val; /* Value for SETVAL 信号量的值*/
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#include
#include
#include
#include
#include
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
void pgetkey(int semid){
struct sembuf sops;
sops.sem_num = 0;//第几位信号量,注意,编号从零开始
sops.sem_op = -1;//操作+1/-1
sops.sem_flg =SEM_UNDO;//标志符IPC_NOWAIT/SEM_UNDO
semop(semid,&sops,1);//sops是一个结构体数组,这里只有一个结构体,所以nsops = 1(第三个参数)
printf("get key\n");
}
void vputbackkey(int semid){
struct sembuf sops;
sops.sem_num = 0;//第几位信号量
sops.sem_op = 1;//操作+1/-1
sops.sem_flg =SEM_UNDO;//标志符IPC_NOWAIT/SEM_UNDO
semop(semid,&sops,1);//sops是一个结构体数组,这里只有一个结构体,所以nsops = 1(第三个参数)
printf("put back key\n");
}
int main(){
int pid;
key_t key;
key = ftok(".",2);
int semid;
union semun initsem;//联合体,根据semctl第三个参数选择,类型要自己定义
initsem.val = 0;//开始是无锁的状态
semid = semget(key,1, IPC_CREAT|0666);//信号量的个数为1
semctl(semid,0,SETVAL,initsem);//0第几个信号量
pid = fork();
if(pid >0){
pgetkey(semid);
printf("this is father\n");
vputbackkey(semid);
semctl(semid,0,IPC_RMID);//销毁第零个信号量
}else if(pid == 0){
// pgetkey(semid);
printf("this is child\n");
vputbackkey(semid);
}else{
printf("fork error\n");
}
return 0;
}