一、无名管道Pipe
示意图:
1)管道就相当于队列的数据结构;
2)管道只适合半双工的通信方式;
3)只能用于具有亲缘关系的进程间通信;
4)管道操作不能同时读和写;读的时候要关闭写端;写的时候要关闭读端;
函数:
#include
int pipe(int pipefd[2]);
说明:
参数:文件描述符:pipefd[0] 是读;pipefd[1] 是写;
返回值:0 成功;其他 失败;
举例:
#include
#include
#include
#include
int main()
{
int fd[2];
int pid;
char *w_count="hello world!";
char r_count[255];
if(pipe(fd)!=0)
{
printf("create pipe fail.\n");
return -1;
}
if((pid=fork())<0)
{
printf("create process fail.\n");
return -1;
}
else if(pid>0)
{
close(fd[0]);
write(fd[1],w_count,strlen(w_count));
close(fd[1]);
wait();
}
else
{
sleep(2);//等待父进程写操作;
close(fd[1]);
read(fd[0],r_count,255);
close(fd[0]);
printf("child read:%s\n",r_count);
}
return 0;
}
运行结果:
[root@localhost ~]# ./pipe
child read:hello world!
二、有名管道FIFO
在shell中,我们可以用mkfifo命令建立一个管道文件:“mkfifo myfifo”;
Fifo突破了pipe只能在父子进程中通信的局限性;这两个不相关的进程通过管道文件建立通信;
函数:
#include
#include
int mkfifo(const char *pathname, mode_t mode);
功能:建立管道文件;然后就可以对文件进行读写操作了;
参数:pathname是路径名称,mode是建立方式;
返回值:0 创建成功;-1 失败;
三、信号
1.(1)
#include
int raise(int sig);
功能:向进程本身发送命令;
(2)
#include
unsigned int alarm(unsigned int seconds);
(3)
#include
#include
int kill(pid_t pid, int sig);
(4)
#include
int pause(void);
2.简单信号处理
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
该函数可以还原为:
#include
void (*signal(int signum, void (*handler))(int)))(int);
第一个参数指定信号的值,第二个参数指定针对前面信号值的处理,可以忽略该信号(参数设为SIG_IGN);可以采用系统默认方式处理信号(参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)。
如果signal()调用成功,返回最后一次为安装信号signum而调用signal()时的handler值;失败则返回SIG_ERR。传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。
举例:#include
#include
#include
void sig_handler(int sig_no)
{
if(sig_no==SIGINT)
{
printf("get SIGINT\n");
}
else if(sig_no==SIGQUIT)
{
printf("get SIGQUIT\n");
}
}
int main()
{
printf("wait for signal\n");
signal(SIGINT,sig_handler);
signal(SIGQUIT,sig_handler);
pause();
return 0;
}
四、共享内存
1.
#include
#include
int shmget(key_t key, size_t size, int shmflg);
功能:开辟内存;
返回值:成功时返回shmID,失败时返回-1 并且记录到error;
2.
#include
#include
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射;也可以用memcpy操作;
返回值:成功时返回地址,失败时返回(void*)-1 并且记录到error;
int shmdt(const void *shmaddr);
功能:关闭映射;
返回值:成功时返回0,失败返回-1;
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:操作内核态的共享空间;
返回值:成功时返回0,失败时返回-1;
举例:/*建立并写入共享内存*/
#include
#include
#include
#include
#include
int main()
{
char contents[]="hello world";
void *share_mem=(void*)0;
int shmid=shmget(123,2046,IPC_CREAT|0666);
if(shmid!=-1)
{
share_mem=shmat(shmid,NULL,0);
if(share_mem!=(void*)-1)
{
memcpy(share_mem,contents,12);
printf("save successed");
shmdt(share_mem);
}
else
{
perror("shmat:");
}
}
else
perror("shmget:");
return 0;
}
执行结果:
[root@localhost ~]# ./chm_write
save successed
/*从共享内存中读出*/
#include
#include
#include
#include
#include
int main()
{
void *share_mem=(void*)0;
int shmid=shmget(123,2046,IPC_CREAT|0666);
if(shmid!=-1)
{
share_mem=shmat(shmid,NULL,0);
if(share_mem!=(void*)-1)
{
printf("get share memery:%s\n",(char*)share_mem);
shmdt(share_mem);
}
else
{
perror("shmat:");
}
}
else
perror("shmget:");
return 0;
}
执行结果:
[root@localhost ~]# ./chm_read
get share memery:hello world
五、消息队列
1.
#include
#include
#include
int msgget(key_t key, int msgflg);
功能:得到消息队列号;
2.
#include
#include
#include
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:发送消息;
消息结构体:struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:接收消息;
注意:消息被取出来后就不存在了;
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:消息控制操作;
举例:
/*msg_send.c*/
#include
#include
#include
#include
#include
struct msgbuf
{
long mtype;
char mtext[255];
} ;
int main()
{
struct msgbuf mybuf;
mybuf.mtype=1;
strcpy(mybuf.mtext,"hello world");
int msgqid=msgget(2345,IPC_CREAT|0666);
if(msgqid!=-1)
{
if(msgsnd(msgqid,&mybuf,sizeof(mybuf.mtext),0)!=-1)
{
printf("send message successed\n");
}
else
perror("msgsend error\n");
}
else
perror("msgget error\n");
return 0;
}
~
运行结果:
[root@localhost app_code]# ./msg_send
send message successed
/*msg_recive.c*/
include
#include
#include
#include
#include
struct msgbuf
{
long mtype;
char mtext[255];
};
int main()
{
struct msgbuf mybuf;
int msgqid=msgget(2345,IPC_CREAT|0666);
if(msgqid!=-1)
{
if(msgrcv(msgqid,&mybuf,sizeof(mybuf.mtext),0,0)!=-1)
{
printf("receive message :%s\n",mybuf.mtext);
}
else
perror("msgrcv error\n");
}
else
perror("msgget error\n");
return 0;
}
[root@localhost app_code]# ./msg_resv
receive message :hello world
六、信号量
1.
#include
#include
#include
int semget(key_t key, int nsems, int semflg);
功能:得到建立信号量;
参数:key:
nsems是要开辟的信号个数;
semflg是标志;
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:信号量的操作;
参数:semid是信号ID;
nsops是信号操作数量;
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg;
}
int semctl(int semid, int semnum, int cmd, ...);
功能:设置信号量;
举例:
#include
#include
#include
#include
#include
int semid;
struct sembuf sem_down={0,-1,0};
struct sembuf sem_up={0,1,0};
void down()
{
semop(semid,&sem_down,1);
}
void up()
{
semop(semid,&sem_up,1);
}
int main()
{
int semid=semget(123,1,IPC_CREAT|0666);
if(semid!=-1)
{
semctl(semid,1,SETVAL);
down();
printf("hello world\n");
sleep(10);
up();
}
else
{
perror("semget error:");
}
return 0;
}
运行结果:
[root@localhost ~]# ./sembol
hello world