消息队列
proto.h rcver.c snder.c
约定双方对话格式 →协议
#ifndef PROTO_H_
#define PROTO_H_
#define KEYPATH "/etc/services"
#define KEYPROJ 'g'
#define NAMESIZE 32
struct msg_st
{
long mtype;
char name[NAMESIZE];
int math;
int chinese;
};
#endif#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include<sys/ipcs.h>
#include<sys/msg.h>
#include<string.h>
#include"proto.h"
int main()
{
struct msg_st sbuf;
int msgid;
key_t key;
key=ftok(KEYPATH,KEYPROJ);
if(key<0)
{
perror("ftok()");
exit(1);
}
msgid=msgget(key,0);
if(msgid<0)
{
perror("msgget()");
exit(1);
}
sbuf.mtype=1;
strcpy(sbuf.name,"Alan");
sbuf.math=rand()%100;
sbuf.chinese=rand()%100;
if(msgsnd(msgid,&sbuf,sizeof(sbuf)-sizeof(long),0)<0)
{
perror("msgsnd()");
exit(1);
}
//谁创建谁销毁
puts("ok!");
exit(0);
}recv先运行,区别 IPC_CREAT
#include <stdio.h>
#include <stblib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include"proto.h"
int main()
{
struct msg_st rbuf;
key_t key;
int msgid;
key=ftok(KEYPATH,KEYPROJ);
if(key<0)
{
perror("ftok()");
exit(1);
}
msgid=msgget(key,IPC_CREAT|0600); //使用权限
if(msgid<0)
{
perror("msgget()");
exit(1);
}
while(1)
{
if(msgrcv(msgid,&rbuf,sizeof(rbuf)-sizeof(long),0,0)<0)
{
perror("msgrcv()");
exit(1);
}
printf("NAME= %s\n",rbuf.name);
printf("MATH = %d\n",rbuf.math);
printf("CHINESE = %d\n".rbuf.chinese);
}
msgctl(msgid,IPC_RMID,NULL);
exit(0);
}ipcrm
myftp_msg
c:path;s:data,n个data包,最后eot 表示当前传输结束。
权限校验
被动端先运行等待接包 ./s 作为守护进程,./c path的内容 重定向到文件或输出到终端 cat
状态机
start状态→发path →失败er→t output

#ifndef PROTO_H__
#define PROTO_H__
#define KEYPATH "etc/services"
#define KEYPROJ 'a'
#define PATHMAX 1024
#define DATAMAX 1024
enum
{
MSG_PATH=1;
MSG_DATA,
MSG_EOT
}
typedef struct msg_path_st
{
long mtype; /*must be MSG_PATH*/
char path[PATHMAX]; /*ASCIZ 带尾0的串*/
}msg_path_t;
typedef struct msg_data_st
{
long mtype;
char data[DATAMAX];
int datalen; //空洞文件 \0 有效数据长度
}msg_data_t;
typedef struct msg_eot_st
{
long mtype;
}msg_eot_st;
union msg_s2c_un
{
long mtype;
msg_data_t datamsg;
msg_eot_t eotmsg;
};
#endifs端只会接一种类型的包 c端接收两种类型的包
2.h
#ifndef PROTO_H__
#define PROTO_H__
#define KEYPATH "etc/services"
#define KEYPROJ 'a'
#define PATHMAX 1024
#define DATAMAX 1024
enum
{
MSG_PATH=1;
MSG_DATA,
MSG_EOT
}
typedef struct msg_path_st
{
long mtype; /*must be MSG_PATH*/
char path[PATHMAX]; /*ASCIZ 带尾0的串*/
}msg_path_t;
typedef struct msg_s2c_st
{
long mtype;
char data[DATAMAX];
int datalen; //空洞文件 \0 有效数据长度
}msg_data_t;
/*datalen>0: data ; datalen=0 : eot*/
#endif利用datalen的结果来确定是data包还是eot包,或者用mtype
信号量数组
信号数组 2 ,每个信号量为1→两个互斥量, 原子操作 锁a和锁b,否则死锁
文件锁下的add.c
p v 操作 取资源与还资源
static int semid;
static void P(void)
{
struct sembuf op;
op.sem_num=0;
op.sem_op=-1;
op.sem_flg=0;
//真错与假错
while(semop(semid,&op,1)<0)
{
if(errno!=EINTR||errno!=EAGAIN)
{
perror("semop()");
exit(1);
}
}
}
static void V(void)
{
struct sembuf op;
op.sem_num=0;
op.sem_op=1;
op.sem_flg=0;
if(semop(semid,&op,1)<0)
{
perror("semop()");
exit(1);
}
}
int main(){
pid_t pid;
int i;
//父子通信 一旦fork所有子进程都拿到
//匿名ipc 用它来写互斥量 一个元素
semid=semget(IPC_PRIVATE,1,0600);
if(semid<0)
{
perror("semget()");
exit(1);
}
if(semctl(semid,0,SETVAL,1)<0)
//资源总量为1
{
perror("semctl()");
exit(1);
}
//销毁
semctl(semid,0,IPC_RMID);
}

shm
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define MEMSIZE 1024
int main()
{
int shmid;
pid_t pid;
char *ptr;
shmid=shmget(IPC_PRIVATE,MEMSIZE,0600);
if(shmid<0)
{
perror("shmget()");
exit(1);
}
pid=fork();
if(pid<0)
{
perror("fork()");
exit(1);
}
if(pid==0) //child write
{
ptr=shmat(shmid,NULL,0);
if(ptr ==(void *) -1)
{
perror("shmat()");
exit(1);
}
strcpy(ptr,"Hello!");
//解除映射
shmdt(ptr);
exit(0);
}
else //parent read
{
wait(NULL);
ptr=shmat(shmid,NULL,0);
if(ptr == (void *)-1)
{
perror("shmat()");
exit(1);
}
puts(ptr);
shmdt(ptr);
shmctl(shmid,IPC_RMID,NULL);
exit(0);
}
}