这两天学习的东西有点多,感觉完全应付不过来了 ,一直在消化这几天学习的东西所以2号、3号、4号的学习内容没有及时总结,在此表示深深的愧疚,今天把这些天学习的知识点汇总一下。
主要学习了IPC进程间通信,目前我所理解的IPC主要包括管道、共享内存、信号量。
总结IPC前先复习一下多进程:
一、进程创建:
1、system函数
通过调用shell程序/bin/sh –c来执行string所指定的命令,该函数在内部是通过调用execve(“/bin/sh”,..)函数来实现的。通过system创建子进程后,原进程和子进程各自运行,相互间关联较少。如果system调用成功,将返回0。
2、fork函数
在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。它和其他函数的区别在于:它执行一次返回两个值。其中父进程的返回值是子进程的进程号,而子进程的返回值为0.若出错则返回-1.因此可以通过返回值来判断是父进程还是子进程。
fork函数创建子进程的过程为:使用fork函数得到的子进程是父进程的一个复制品,它从父进程继承了进程的地址空间,包括进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端,而子进程所独有的只有它的进程号、资源使用和计时器等。通过这种复制方式创建出子进程后,原有进程和子进程都从函数fork返回,各自继续往下运行,但是原进程的fork返回值与子进程的fork返回值不同,在原进程中,fork返回子进程的pid,而在子进程中,fork返回0,如果fork返回负值,表示创建子进程失败。(vfork函数)
3、exec函数族
exec*由一组函数组成
int execl(const char *path, const char *arg, ...)
exec函数族的工作过程与fork完全不同,fork是在复制一份原进程,而exec函数是用exec的第一个参数指定的程序覆盖现有进程空间(也就是说执行exec族函数之后,它后面的所有代码不在执行)。
path是包括执行文件名的全路径名
arg是可执行文件的命令行参数,多个用,分割注意最后一个参数必须为NULL。
二、共享内存与信号量
共享内存机制主要用到 shmget shmat shmdt shmctl 函数;
原理及实现:system V IPC机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。这样一个使用共享内存的进程可以将信息写入该空间,而另一个使用共享内存的进程又可以通过简单的内存读操作获取刚才写入的信息,使得两个不同进程之间进行了一次信息交换,从而实现进程间的通信。共享内存允许一个或多个进程通过同时出现在它们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条目所引用,同时并不需要在所有进程的虚拟内存都有相同的地址。进程对象对于共享内存的访问通过key(键)来控制,同时通过key进行访问权限的检查。
shmget 通过关键字建立共享内存;
shmat 返回共享内存地址
shmdt 断开与共享内存的链接
Shmctl 回收共享内存
三、IPC进程通信的应用:select多进程服务器
头文件:
#ifndef __CLINET_H__
#define __CLINET_H__
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
typedef struct tag
{
int m_flag ;
char m_buf[1024] ;
}MBUF, *pMBUF;
void P(int semid) ;
void V(int semid);
#endif
客户端输入端:
/*************************************************************************
> File Name: client_in.c
> Author: Comst
> Mail:[email protected]
> Created Time: Wed 04 Feb 2015 03:04:39 PM CST
************************************************************************/
#include "client.h"
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/fcntl.h>
#define PATH "/home/comst/pipe"
#define SERVER "server.fifo"
int main(int argc, char* argv[])//shm_key sem_key
{
char server_name[128]= "" ;
char read_file[128], write_file[128] ;
char msg[32] ="" ;
int fd_r, fd_w ;
sprintf(server_name, "%s/%s", PATH, SERVER);
int fd_server = open(server_name, O_WRONLY);
memset(read_file, 0, 128);
memset(write_file, 0, 128);
sprintf(read_file, "%s/%d_r.fifo", PATH, getpid());
sprintf(write_file, "%s/%d_w.fifo", PATH, getpid());
mkfifo(read_file, 0666);
mkfifo(write_file, 0666);
sprintf(msg, "%d\n", getpid());
write(fd_server, msg, strlen(msg));
fd_r = open(read_file, O_RDONLY);
fd_w = open(write_file, O_WRONLY);
key_t shm_key, sem_key ;
int my_shm, my_sem ;
char line[1024] ;
pMBUF p ;
shm_key = (key_t)atoi(argv[1]);
sem_key = (key_t)atoi(argv[2]);
my_shm = shmget(shm_key, sizeof(MBUF), 0666|IPC_CREAT);
my_sem = semget(sem_key, 1, 0666 | IPC_CREAT);
semctl(my_sem, 0, SETVAL, 1);
p = (pMBUF)shmat(my_shm, NULL, 0);
memset(p, 0, sizeof(MBUF));
while(memset(line, 0, 1024), fgets(line, 1024, stdin) != NULL)
{
write(fd_w, line, strlen(line));
memset(line, 0, 1024);
read(fd_r, line, 1024);
while( P(my_sem), p -> m_flag == 1)
{
V(my_sem);
sleep(1);
}
strcpy(p ->m_buf, line);
p ->m_flag = 1 ;
V(my_sem);
}
while( P(my_sem), p -> m_flag == 1)
{
V(my_sem);
sleep(1);
}
strcpy(p ->m_buf, "over");
p ->m_flag = 1 ;
V(my_sem);
sleep(3);
shmdt(p);
shmctl(my_shm, IPC_RMID, NULL) ;
semctl(my_sem, 0, IPC_RMID);
}
客户端输出端:
/*************************************************************************
> File Name: client_out.c
> Author: Comst
> Mail:[email protected]
> Created Time: Wed 04 Feb 2015 03:04:39 PM CST
************************************************************************/
#include "client.h"
int main(int argc, char* argv[])//shm_key sem_key
{
key_t shm_key, sem_key ;
int my_shm, my_sem ;
char line[1024] ;
pMBUF p ;
shm_key = atoi(argv[1]);
sem_key = atoi(argv[2]);
my_shm = shmget(shm_key, sizeof(MBUF), 0666);
my_sem = semget(sem_key, 1, 0666 );
semctl(my_sem, 0, SETVAL, 1);
p = (pMBUF)shmat(my_shm, NULL, 0);
memset(p, 0, sizeof(MBUF));
while(1)
{
while(P(my_sem), p -> m_flag == 0)
{
V(my_sem);
sleep(1);
}
printf("%d : %s\n", getpid(), p -> m_buf);
if(strcmp(p ->m_buf, "over") == 0)
{
V(my_sem);
break ;
}
p -> m_flag = 0 ;
V(my_sem);
}
shmdt(p);
}
功能函数:
/*************************************************************************
> File Name: ./func.c
> Author: Comst
> Mail:[email protected]
> Created Time: Wed 04 Feb 2015 03:17:06 PM CST
************************************************************************/
#include "client.h"
void P(int semid)
{
struct sembuf my_buf ;
memset(&my_buf, 0, sizeof(my_buf) );
my_buf.sem_num = 0 ;
my_buf.sem_op = -1 ;
my_buf.sem_flg = SEM_UNDO ;
semop(semid, &my_buf, 1);
}
void V(int semid)
{
struct sembuf my_buf ;
memset(&my_buf, 0, sizeof(my_buf) );
my_buf.sem_num = 0 ;
my_buf.sem_op = 1 ;
my_buf.sem_flg = SEM_UNDO ;
semop(semid, &my_buf, 1);
}
服务器:
/*************************************************************************
> File Name: server.c
> Author: Comst
> Mail:[email protected]
> Created Time: Wed 04 Feb 2015 04:40:58 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<signal.h>
#define PATH "/home/comst/pipe"
#define NAME "server.fifo"
void child_handle(int sig_num)
{
printf("a child exit!\n");
wait(NULL);
}
void reverse(char* str)
{
int bg, end ;
char tmp ;
bg = 0 ;
end = strlen(str) - 1 ;
while(bg < end)
{
tmp = str[bg] ;
str[bg] = str[end] ;
str[end] = tmp ;
bg ++ ;
end -- ;
}
}
void child_main(int fd_rd, int fd_wr)
{
char buf[1024] ;
while(memset(buf, 0, 1024), read(fd_rd, buf, 1024) != 0)
{
reverse(buf);
write(fd_wr, buf, strlen(buf));
}
}
int main(int argc, char* argv[])
{
signal(17, child_handle);
char file_name[128] = "";
char client_r[128], client_w[128];
char line[32] ;
int fd_read ;
int client_id ;
int fd_cr , fd_cw ;
FILE* fp ;
sprintf(file_name, "%s/%s", PATH, NAME);
mkfifo(file_name, 0666) ;
fd_read = open(file_name, O_RDONLY);
open(file_name, O_WRONLY);
fp = fdopen(fd_read, "r");
while(memset(line, 0 , 32), fgets(line, 32, fp) != NULL)// "pid\n"
{// cr cw pid_r.fifo pid_w.fifo
sscanf(line, "%d", &client_id);
printf("client: %d request !\n", client_id) ;
memset(client_r, 0, 128);
memset(client_w, 0, 128);
sprintf(client_r, "%s/%d_r.fifo", PATH, client_id);
sprintf(client_w, "%s/%d_w.fifo", PATH, client_id);
fd_cw = open(client_r, O_WRONLY);
fd_cr = open(client_w, O_RDONLY);
if(fork() == 0)
{
child_main(fd_cr, fd_cw);
close(fd_cr);
close(fd_cw);
exit(1);
}
close(fd_cr);
close(fd_cw);
}
memset(file_name, 0, 128);
sprintf(file_name, "%s/%s", PATH, NAME);
unlink(file_name);
return 0 ;
}