1
对于有名管道的创建必须是在home目录下,路径也写上,进入home后ls后发现黄色的文件就是,开启两个终端,在一个中端写入,另一个终端上vim进入里面显示。
2两个进程同时跑,有一个进程在vi里面创建才能跑,跑的图片如下,即使通过管道建立两个没有联系的进程中联系,并且一个写,一个读
#include <unistd.h>
#include <stdio.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SIZE 1024
// 在管道读或者写入数据
int main1()
{
FILE *fp =popen("ps -ef","r");
if (fp==NULL)
{
perror("popen");
return -1;
}
char buf [SIZE]={0};
int ret=fread(buf,sizeof(char),SIZE-1,fp);
//此时不能写入ret,否则是段错误,成功读到数据缓冲区的个数
printf("读到的数据:\n %s\n",buf);
FILE *fp2 =popen("grep a.out","w");
if (fp2==NULL)
{
perror("popen");
return -1;
}
fwrite (buf,sizeof(char),ret,fp2);
printf("写入完成\n");
pclose(fp);
fclose(fp2);
return 0;
}
// 单个进程之间的管道
int main2()
{
int fd[2];
int ret =pipe(fd);
if (ret == -1)
{
perror("pipe");
return -1;
}
ret =write (fd[1],"hello",5);
printf("写入%d 个字节\n",ret);
char ch;
while(1)//这个死循环表示一个一个读取,但是最后可能没有0返还,并没有结束
{
ret =read(fd[0],&ch,1);
if (ret==-1)
{
perror("read");
return -1;
}
printf("读到的 %d字节: %c\n",ret,ch);
}
//ret便是读到个数就是一个一个读的,ch储存在里面的字节
close(fd[0]);
close(fd[1]);
return 0;
}
void child_do1(int *fd)
{
//子进程通过管道读取父进程的数据,并且关闭自己的
//的写端
close(fd[1]);
char buf [SIZE];
while (1)
{
int ret=read(fd[0],buf,SIZE-1);
if(ret==-1)
{
perror("read");
break;
}
buf[ret]='\0';
printf("子进程读到的%d 字节数据: %s\n",ret,buf);
}
close(fd[0]);
}
void father_do1(int *fd)
{
//父进程通过管道想子进程发送自己的数据,并且关闭
//自己的读端
close(fd[0]);
char buf[SIZE];
while (1)
{
fgets(buf,SIZE,stdin);
//表示从标准输入写入数据存在buf里面,这个参数就是
int ret =write (fd[1],buf,strlen(buf));
if (ret== -1)
{
perror ("write");
return ;
}
}
close(fd[1]);
}
int main3()
{
//建立管道
int fd[2];
int ret=pipe(fd);
if (ret==-1)
{
perror("pipe");
return -1;
}
//创建进程
pid_t pid =fork();
switch(pid)
{
case -1:
perror("fork");
break;
case 0:
child_do1(fd);
break;
default :
father_do1(fd);
break;
}
return 0;
}
void child_do2(int *fd)
{
//子进程通过管道读取父进程的数据,并且关闭自己的
//的写端
close(fd[1]);
int fd_write=open("2.ppt",O_WRONLY|O_CREAT,0777);
if(fd_write==-1)
{
perror("open");
return;
}
int ret;
char buf[SIZE];
while (ret=read(fd[0],buf,SIZE-1))
{
//先从管道里读取数据到缓冲区
buf[ret]='\0';
// 从管道读取数据,如果管道没有数据可读,read会阻塞,如果管道的写段被关闭,read
// 返回0;
if(ret==-1)
{
perror("read");
break;
}
write(fd_write,buf,ret);
//先把缓冲区里的数据读到你创建的文件2.ppt里
}
printf("复制完成\n");
close(fd_write);
close(fd[0]);
}
void father_do2 (int *fd)
{
//父进程通过管道想子进程发送自己的数据,并且关闭
//自己的读端
close(fd[0]);
int fd_read=open("1.ppt",O_RDONLY);
if(fd_read==-1)
{
perror("read");
return;
}
int ret;
char buf[SIZE];
while (ret = read(fd_read,buf,SIZE))
{
buf[ret]='\0';
if (ret==-1)
{
perror("read");
break;
}
write(fd[1],buf,ret);
}
close(fd_read);
close(fd[1]);
}
int main4()
{
//建立管道
int fd[2];
int ret=pipe(fd);
if (ret==-1)
{
perror("pipe");
return -1;
}
//创建进程
pid_t pid =fork();
switch(pid)
{
case -1:
perror("fork");
break;
case 0:
child_do2(fd);
break;
default :
father_do2(fd);
break;
}
return 0;
}
void child_do(int *fd)
{
close(fd[1]);
close(fd[0]);
//将孩子进程的读写端全部关闭
}
void father_do(int *fd)
{
close(fd[0]);
printf ("等待子进程关闭读端\n");
sleep(2);
// 所有读端都关闭了,写端继续往管道写入数据
// 如果管道所有的读端都被关闭,继续写数据系统默认的操作是使程序退出
write (fd[1], "hello", 5);
printf ("11111111111111111111111111111111\n");
// 关闭写端
close(fd[1]);
//说明管道是一端读一端写的,先进先出,关闭任何一段将无法读写数据
}
int main5()
{
//建立管道
int fd[2];
int ret=pipe(fd);
if (ret==-1)
{
perror("pipe");
return -1;
}
//创建进程
pid_t pid =fork();
switch(pid)
{
case -1:
perror("fork");
break;
case 0:
child_do(fd);
break;
default :
father_do(fd);
break;
}
return 0;
}
int main6()
{
int ret = mkfifo("/home/wode", 0777);
//必须在home目录下,不能在共享文件下,可能就是管道连接
//两个目录,进入home里面你就会看见
if (ret == -1)
{
perror ("mkfifo");
return -1;
}
return 0;
}
int main7()
{
int fd=open("/home/wode",O_WRONLY);
if(fd== -1)
{
perror("open");
return -1;
}
char buf[SIZE];
while(1)
{
fgets(buf,SIZE,stdin);
write(fd,buf,strlen(buf));//将标准输入的内容打进以前创建的有名管道里
}
//从朴准输入里输入,打开两个终端,你会发现home目录下显示
//share里面输入的内容
return 0;
}
int main8()
{
int fd = open("/home/mkfifo", O_RDWR);
if (fd == -1)
{
perror ("mkfifo");
return -1;
}
char buf[SIZE];
while (1)
{
int ret = read (fd, buf, SIZE);
buf[ret] = '\0';
sleep(1);
printf ("读到 %d 字节: %s\n", ret, buf);
}
return 0;
}
// 将七八两个放在两个终端上联系,并且用两个gcc,你会发现两个进程对同一个
//程序控制,这就是所谓的有名管道之间的联系
//但是在终端上进去才能建立两者之间的循环,具体原因我也不知道
typedef struct _shm
{
int flag;
char msg[256];
}SHM;//定义一个结构体共享内存
int main9()
{
// 1、创建或者获取一个共享内存
int shmid = shmget((key_t)1234, sizeof(SHM), 0666 | IPC_CREAT);
if (shmid == -1)
{
perror ("shmget");
return -1;
}
// 2、将共享内存映射到当前的进程空间
SHM* pshm = (SHM*)shmat(shmid, NULL, 0);
//强制装换为共享内存的类型,并且第一个参数是由shmget返回的
//共享内存标识符
if(pshm == (SHM*)-1)
{
perror ("shmat");
return -1;
}
strcpy (pshm->msg, "hello");
printf("共享内存里写入: %s\n",pshm->msg);
// 解除共享内存映射,解除是值当前进程不能再使用共享内存
shmdt(pshm);
//参数是有shmat映射到进程里面的共享指针
shmctl(shmid, IPC_RMID, NULL);
//第一个参数是共享内存标示符,第二个参数是删除,第三个是一个指针,指向共享内存
//模式和访问的结构,此时设置为空
return 0;
}
int main()
{
// 1、创建或者获取一个共享内存
int shmid = shmget((key_t)1234, sizeof(SHM), 0666 | IPC_CREAT);
if (shmid == -1)
{
perror ("shmget");
return -1;
}
sleep(10);
// 2、将共享内存映射到当前的进程空间
SHM* pshm = (SHM*)shmat(shmid, NULL, 0);
if(pshm == (SHM*)-1)
{
perror ("shmat");
return -1;
}
printf ("%s\n", pshm->msg);
// 就是进入共享内存里面
return 0;
}