/***************************************************************************************************************************
该程序编译好后,需要运行两次(都保持不退出),第一次运行相当于进程1,第二次运行相当于进程2,
进程1向共享内存写数据,进程2从共享内存读数据。输入quit则进程全部退出,并删除共享内存
***************************************************************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/shm.h>
#define N 1024
void handler(int signo){};
int main()
{
key_t key;
int shmid;
pid_t peerid;
char *shmaddr;
struct shmid_ds buf;
signal(SIGUSR1, handler); //注册SIGUSR1信号。如果不注册该信号,那么一旦接收到该信号,进程就会被杀死。handler函数什么也不做,因此该信号的功能只是唤醒该进程。
if ((key = ftok("/", 10)) == -1) //根据文件的inode节点来生成key。为了使进程能根据相同的文件inode节点来得到相同的key,
{ //最好选择那些稳定的文件名(或目录名)来生成key,本例中使用了根目录的inode来生成key
perror("ftok");
return -1;
}
if ((shmid = shmget(key, N, 0666 | IPC_CREAT | IPC_EXCL)) == -1) //获取共享内存的id号
{
if (errno == EEXIST) //如果共享内存存在,那么就打开共享内存
{
printf("second....");
shmid = shmget(key, N, 0666);
if ((shmaddr= (char*)shmat(shmid, NULL, 0))== (char*)-1) //将共享内存映射到用户空间,并把首地址传给shmaddr
{
perror("shmat second");
return -1;
}
peerid = atoi(shmaddr); //获取第一个进程的ID
sprintf(shmaddr, "%d", getpid()); //将自己的ID写入共享内存
kill(peerid, SIGUSR1); //唤醒第一个进程
while (1)
{
pause();
if (strncmp(shmaddr, "quit", 4) == 0)
break;
fputs(shmaddr, stdout); //从共享内存读数据
kill(peerid, SIGUSR1); //读完数据后唤醒进程1
}
}
else { perror("shmget second"); return -1;}
}
else
{
printf("first....");
if ((shmaddr = (char*)shmat(shmid, NULL, 0)) == (char*)-1) //创建共享内存
{
perror("shmat first");
return -1;
}
sprintf(shmaddr, "%d", getpid()); //将自己的ID写入共享内存,以便进程2读取
pause();
peerid = atoi(shmaddr); //获取进程2的ID
while (1)
{
if (fgets(shmaddr, N, stdin) == NULL) //向共享内存写数据
{
perror("fgets");
return -1;
}
if (strncmp(shmaddr, "quit", 4) == 0)
{
kill(peerid, SIGUSR1);
break;
}
kill(peerid, SIGUSR1); //写完数据后唤醒进程2
pause();
}
}
if (shmdt(shmaddr) == -1) //取消共享内存映射
{
perror("shmdt");
return -1;
}
if (shmctl(shmid, IPC_STAT, &buf) == -1) //获取共享内存的状态信息,保存在buf里
{
perror("shmctl");
return -1;
}
if (buf.shm_nattch == 0)
{
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
if(errno != EINVAL) //如果报错的原因是共享内存已经被删除,则什么也不做。如果是其他原因,则打印错误信息
{
perror("chmctl rm ");
return -1;
}
exit(-1);
};
}
return 0;
}
该程序编译好后,需要运行两次(都保持不退出),第一次运行相当于进程1,第二次运行相当于进程2,
进程1向共享内存写数据,进程2从共享内存读数据。输入quit则进程全部退出,并删除共享内存
***************************************************************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/shm.h>
#define N 1024
void handler(int signo){};
int main()
{
key_t key;
int shmid;
pid_t peerid;
char *shmaddr;
struct shmid_ds buf;
signal(SIGUSR1, handler); //注册SIGUSR1信号。如果不注册该信号,那么一旦接收到该信号,进程就会被杀死。handler函数什么也不做,因此该信号的功能只是唤醒该进程。
if ((key = ftok("/", 10)) == -1) //根据文件的inode节点来生成key。为了使进程能根据相同的文件inode节点来得到相同的key,
{ //最好选择那些稳定的文件名(或目录名)来生成key,本例中使用了根目录的inode来生成key
perror("ftok");
return -1;
}
if ((shmid = shmget(key, N, 0666 | IPC_CREAT | IPC_EXCL)) == -1) //获取共享内存的id号
{
if (errno == EEXIST) //如果共享内存存在,那么就打开共享内存
{
printf("second....");
shmid = shmget(key, N, 0666);
if ((shmaddr= (char*)shmat(shmid, NULL, 0))== (char*)-1) //将共享内存映射到用户空间,并把首地址传给shmaddr
{
perror("shmat second");
return -1;
}
peerid = atoi(shmaddr); //获取第一个进程的ID
sprintf(shmaddr, "%d", getpid()); //将自己的ID写入共享内存
kill(peerid, SIGUSR1); //唤醒第一个进程
while (1)
{
pause();
if (strncmp(shmaddr, "quit", 4) == 0)
break;
fputs(shmaddr, stdout); //从共享内存读数据
kill(peerid, SIGUSR1); //读完数据后唤醒进程1
}
}
else { perror("shmget second"); return -1;}
}
else
{
printf("first....");
if ((shmaddr = (char*)shmat(shmid, NULL, 0)) == (char*)-1) //创建共享内存
{
perror("shmat first");
return -1;
}
sprintf(shmaddr, "%d", getpid()); //将自己的ID写入共享内存,以便进程2读取
pause();
peerid = atoi(shmaddr); //获取进程2的ID
while (1)
{
if (fgets(shmaddr, N, stdin) == NULL) //向共享内存写数据
{
perror("fgets");
return -1;
}
if (strncmp(shmaddr, "quit", 4) == 0)
{
kill(peerid, SIGUSR1);
break;
}
kill(peerid, SIGUSR1); //写完数据后唤醒进程2
pause();
}
}
if (shmdt(shmaddr) == -1) //取消共享内存映射
{
perror("shmdt");
return -1;
}
if (shmctl(shmid, IPC_STAT, &buf) == -1) //获取共享内存的状态信息,保存在buf里
{
perror("shmctl");
return -1;
}
if (buf.shm_nattch == 0)
{
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
if(errno != EINVAL) //如果报错的原因是共享内存已经被删除,则什么也不做。如果是其他原因,则打印错误信息
{
perror("chmctl rm ");
return -1;
}
exit(-1);
};
}
return 0;
}