无名管道
命名管道
消息队列
共享内存
信 号
信号量
1,无名管道
函数pipe()
头文件
#include <unistd.h>
函数原型
int pipe(int pipefd[2]);
pipefd[2]:定义个整型数组其中pipefd[1]为读,pipefd[2]为写,一个进程只能读或则只能写(父与子通信)
return:成功为0,错误为-1
2,命名管道
函数原型mkfifo [OPTION] 例如 mkfifo(“./file”,0600)
file:创建的管道文件名称
0600:权限
使用文件进行两个进程之间的通信
return :错误为-1
3,消息队列
主要用到5个api
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
a,ftok() (创建key值)
函数原型:key_t ftok(const char *pathname, int proj_id);
const char *pathname:一般为“.”,.代表当前文件路径。
int proj_id :一般为任意一个数字(6)或则字符(‘z’)
return:会生成一个key值。
b,msgget()(创建消息队列)
函数原型:int msgget(key_t key, int msgflg);
key:由ftok()函数生成的一个key值
int msgflg:一般为IPC_CREAT|0777。创建管道加权限
return:为一个消息队列号
c,msgsnd()函数 (发送消息)
函数原型int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
int msqid:为消息队列号
const void msgp:是一个结构体:初始化结构体
struct msgbuf {
long mtype; / message type, must be > 0 /发送的数据类型
char mtext[1]; / message data */发送的内容
};
size_t msgsz:发送的内容的大小
int msgflg:一般为0,意思为非阻塞
D,msgrcv()函数(接收消息)
函数原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
int msqid:为消息队列号
void msgp:
struct msgbuf {
long mtype; / message type, must be > 0 /
char mtext[1]; / message data */
};
size_t msgsz:接收的内容的大小
long msgtyp:接收的数据类型
int msgflg:一般为0,意思为阻塞
E,msgctl()可以删除消息队列
函数原型int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msqid:为消息队列号
int cmd:一般为IPC_RMID
struct msqid_ds *buf:一般为NULL
接收然后在发送例子
#include<string.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf
{
long mtype;
char mtext[128];
};
int main()
{
struct msgbuf readBuf;
struct msgbuf sendBuf = {999,"this is cool"};
int key = ftok(".", 'a');
printf("key = %d\n",key);
int msgID = msgget(key,IPC_CREAT|0777);
if(msgID == -1){
printf("creat pipe failing\n");
}
int ret = msgrcv(msgID, &readBuf, sizeof(readBuf), 888,0);
if(ret != -1){
printf("receive successfully\n");
printf("from another processing:%s\n",readBuf.mtext);
sleep(3);
}
int ret1 = msgsnd(msgID, &sendBuf, strlen(sendBuf.mtext),0);
if(ret1 == 0){
printf("send successfully\n");
}
msgctl(msgID,IPC_RMID,NULL);
return 0;
}
发送在接收
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf sendBuf = {888,"this is mine"};
struct msgbuf readbuf;
int key = ftok(".", 'a');
printf("key =%d \n",key);
int msgID = msgget(key,IPC_CREAT|0777);
if(msgID == -1){
printf("creat pipe failing\n");
}
int ret = msgsnd(msgID, &sendBuf, strlen(sendBuf.mtext),0);
if(ret == 0){
printf("send successfully\n");
sleep(3);
}
msgrcv(msgID, &readbuf, sizeof(readbuf), 999,0);
if(ret != -1){
printf("receive successfully\n");
printf("from another processing:%s\n",readbuf.mtext);
}
msgctl(msgID,IPC_RMID,NULL);
return 0;
}
4,共享内存
5个api: ftok(),shmget(),shmat(),shmctl(),shmdt()
A,ftok()同上面消息队列是一致的
B,shmget():打开或创建共享内存
头文件
#include <sys/types.h>
#include <sys/shm.h>
函数原型
int shmget(key_t key, size_t size, int shmflg);
size_t size:共享内存大小
shmflg:共享内存大小
return:为共享内存的标识符
C,shmat(),shmdt():映射
头文件
#include <sys/types.h>
#include <sys/shm.h>
函数原型
void *shmat(int shmid, const void *shmaddr, int shmflg);挂载
shmid:共享内存标识符
shmaddr: 一般为0,系统自动分配内存
shmflg:标志位一般为0,可读可写
shmat()的返回值:为挂载到该进程的地址用一个字符指针来接收
int shmdt(const void *shmaddr);切断挂载
shmaddr:shmat()的返回值
D,shmctl()删除共享内存和共享队列一样
注:ipcs -m 查找当前的共享内存
ipcrm±m+共享内存号(删除该共享内存)(+为空格)
写
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include<string.h>
int main()
{
// int shmget(key_t key, size_t size, int shmflg);
key_t key;
int getshare;
char *shm;
key = ftok(".",1);
getshare = shmget(key,1024*4,IPC_CREAT|0666);
shm = shmat(getshare,0,0);
strcpy(shm,"shandsome");
sleep(5);
shmdt(shm);
shmctl(getshare,IPC_RMID,0);
return 0;
}
读
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
// int shmget(key_t key, size_t size, int shmflg);
key_t key;
int getshare;
char *shm ;
key = ftok(".",1);
getshare = shmget(key,1024*4,0);
shm = shmat(getshare,0,0);
printf("%s\n",shm);
shmdt(shm);
return 0;
}
5,信号
见文章 https://www.jianshu.com/p/f445bfeea40a
例程
读
#include<stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
// int sigaction(int signum, const struct sigaction *act,
// struct sigaction *oldact);
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);
printf("from another process:%d\n",info->si_pid);
}
}
int main()
{
struct sigaction act;
printf("this process:%d\n",getpid());
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1,&act,NULL);
while(1);
return 0;
}
发
#include<stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
// int sigqueue(pid_t pid, int sig, const union sigval value);
int main(int argc,char **argv)
{
int signum = atoi(argv[1]);
int pid = atoi(argv[2]);
union sigval value;
value.sival_int = 100;
sigqueue(pid,signum,value);
printf("pid=%d\n",getpid());
return 0;
}
信号和共享内存的使用
接收
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
void sigusr1_handler(int signum, siginfo_t *info, void *context) {
// 信号处理函数仅用于标记信号已接收
printf("SIGUSR1 received.\n");
}
int main() {
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &sigusr1_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("Receiver process started. PID: %d\n", getpid());
// 创建和附加共享内存
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*) shmat(shmid, (void*)0, 0);
// 等待信号
pause();
// 读取共享内存中的数据
printf("Data received: %s\n", str);
// 分离和销毁共享内存
shmdt(str);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
发送
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*) shmat(shmid, (void*)0, 0);
printf("Writing to shared memory: \"Hello, World!\"\n");
strncpy(str, "Hello, World!", 1024);
pid_t pid;
printf("Enter the PID of the receiver process: ");
scanf("%d", &pid);
union sigval value;
value.sival_int = 0;
if (sigqueue(pid, SIGUSR1, value) == -1) {
perror("sigqueue");
}
// 等待接收进程读取数据
sleep(5);
shmdt(str);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
6,信号量
3个api
semget(),semctl(),semop()
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
// int semget(key_t key, int nsems, int semflg);
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 id)
{
// int semop(int semid, struct sembuf *sops, unsigned nsops);
struct sembuf set;
set.sem_num = 0;
set.sem_op = -1;
set.sem_flg = SEM_UNDO;
semop(id,&set,1);
printf("get the key\n");
}
void vputkey(int id)
{
// int semop(int semid, struct sembuf *sops, unsigned nsops);
// semid:信号量id。sops设置信号量放下参数。nsops:信号量个数
struct sembuf set;
set.sem_num = 0;
set.sem_op = 1;
set.sem_flg = SEM_UNDO;
semop(id,&set,1);
printf("put back the key\n");
}
int main()
{
key_t key;
key = ftok(".",2);
int semid;
semid = semget(key,1,IPC_CREAT|0666);//创建信号量
union semun initsem;
initsem.val = 0;
// int semctl(int semid, int semnum, int cmd, ...);
// semnum:操作第几个信号量
semctl(semid,0,SETVAL,initsem);//初始化信号量
int pid = fork();
if(pid > 0){
pGetkey(semid);
printf("this is father\n");
vGetkey(semid);
}
else if(pid == 0)
{
vputkey(semid);
printf("this is son\n");
}
return 0;
}
师上官可编程