网站地图的形式,广州网站设计成功柚米,WordPress 发表文章api,阳江房产网官网复制文件描述符
dup函数
作用#xff1a;
文件描述符复制
语法#xff1a; #include unistd.h int dup (int oldfd);
参数#xff1a; 所需复制得文件描述符
返回值#xff1a; 复制到的文件描述符
功能#xff1a; 从文件描述符表中#xff0c;找一个最小…复制文件描述符
dup函数
作用
文件描述符复制
语法 #include unistd.h int dup (int oldfd);
参数 所需复制得文件描述符
返回值 复制到的文件描述符
功能 从文件描述符表中找一个最小可能的文件描述符通过返回值返回作为oldfd复制
示例1
#include stdio.h
#include unistd.h
int main(int argc, char const *argv[])
{int newpd dup(1);write(newpd,hello world\n,12);return 0;
}dup2函数推荐
函数
#include unistd.h
int dup2(int oldfd,int newfd);
参数
oldfd原文件描述符
newfd指定复制到的文件描述符如果该文件描述符已存在那将已存在的关闭
示例
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
int main(int argc, char const *argv[])
{int fd open(huange.txt,O_WRONLY | O_CREAT | O_APPEND,0666);int pd dup2(fd,1);printf(娶你明年\n);return 0;
}无名管道
概述 又名管道 (pipe) 无名管道是一种特殊类型的文件在应用层体现为两个打开的文件描述符 ,1 个描述符写 fd[1] 1 个描述符读 fd[0] 核心0读1写 特点 1.管道不是普通的文件不属于某个文件管理系统存在于内存中 2.半双工数据在同一时间只能在单向传输 补充 单工指数据只能在单向传输数据 双工指在两台通讯设备之间允许有双向的数据传输 全双工允许两台通讯设备之间同时进行双向数据传输。一般的电话手机就是全双工系统因为在讲话的同时也能听到对方的声音。 半双工允许两台通讯设备之间进行双向数据传输但不能同时进行。因此同一时间只允许一个设备进行传输数据若另一设备需要传输数据则需要等待上一个传输数据的设备传输结束后才可以传输数据。 3.数据只允许从管道的一端写入从管道的另一端读取 4.写入管道中的数据遵循先入先出的原则 5.管道所传输的数据是无格式的这要求管道的读出方和写入放提前商量好一个文件的格式如多少字节算一则消息 6.管道在内存中对应一个缓冲区。不通的系统所对应的大小不一样。 7.数据从管道中读取是一次性操作管道中数据一旦被读取管道就会抛弃该数据以便于释放空间来写入其它数据 8.管道没有名字只能在具有公共祖先的进程中使用 补充 管道可以用于任意两个或更多相关进程之间的通信只要在创建子进程 的系列调用之前通过一个共同的祖先进程创建管道即可。 如管道可用于一个进程和其子孙进程之间的通信。第一个进程创建管道然后创建子进程接着子进程再创建第一个进程的孙子进程。 管道通常用于两个兄弟进程之间的通信—— 它们的父进程创建了管道并创建两个子进程。 pipe函数
作用:用于创建无名管道
语法
#include unistd.h
int fd[] ;
pipe(fd);
参数
fd为int型数据的首元素地址其存放了管道的文件描述符反对fd[0],fd[1]
f[0]为读而打开管道f[1]为写而打开
返回值 成功:0 失败-1
int fd[2];
pipe(fd);
示例
#include stdio.h
#include unistd.h
#include sys/wait.h
#include sys/types.h
int main(int argc, char const *argv[])
{int fd[2];pipe(fd);int i 0;for(i 0;i 2;i){int pid fork();if(pid 0){break;}}if(i 0){close (fd[0]);char buf[] hello to2;write(fd[1],buf,sizeof(buf));close(fd[1]);_exit(0);}else if(i 1){close (fd[1]);char buf[60] {0};read(fd[0],buf,sizeof(buf));close(fd[0]);printf(%s\n,buf);_exit(0);}else if(i 2){while(1){int pid waitpid(-1,NULL,WNOHANG);if(pid 0){break;}}}return 0;
} 读写特点
1.默认用read函数从管道中读取数据时是阻塞的
2.调用write函数写入时当管道的缓冲区已满时也会发生阻塞管道的缓冲区大小时65kb
3.通信过程中读端口全部关闭后写进程向管道内写数据时写进程会收到SIGPIPE 信号退出。
4.从管道中读取数据的特点 编程时可通过fcntl函数设置文件的阻塞特性。设置为阻塞fcntlfd,FSETFL,O_NONBLOCK);
示例一缓冲区已满时 write 也会阻塞。
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include stdlib.h
int main(int argc, char const *argv[])
{int fd[2] ;pipe(fd);int pid fork();if(pid 0){close(fd[1]);sleep(2);close(fd[0]);_exit(0);}else if(pid 0){close(fd[0]);//关闭读int count 0;for(int i 0;i 10000;i){int buf[1024] {0};printf(buf%ld\n,sizeof(buf)/sizeof(buf[0]));write(fd[1],buf,1024);count 1024;printf(i%d\ncount%d\n,i,count);} close(fd[1]);wait(NULL);}return 0;
}#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
int main(int argc, char const *argv[])
{//证明:调用 write 函数向管道里写数据当缓冲区已满时 write 也会阻塞int fd[2];pipe(fd);for (int i 0; i 1000; i){char buf[1024] {0};write(fd[1],buf,1024);printf(i %d\n,i);}printf(OVER\n);return 0;
} 示例二通信过程中写端关闭读端将解阻塞
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include stdlib.h
int main(int argc, char const *argv[])
{int fd[2];pipe(fd);int pid fork();if(pid 0){close(fd[1]);int buf[100] {0};printf(开始读取\n);read(fd[0],buf,100);close(fd[0]);printf(读取结束\n);_exit(0);}else if(pid 0){close(fd[0]);sleep(2);close(fd[1]);sleep(5);_exit(0);}return 0;
}示例三通信过程中 读端关闭 写端将收到SIGPIPE信号 退出写端进程
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include sys/stat.h
#include fcntl.h
int main(int argc, char const *argv[])
{int fd[2];pipe(fd);int pid fork();if (pid 0){close(fd[1]);while (1){int i 0;char buf[128] ;int len read(fd[0], buf, sizeof(buf) / sizeof(buf[0]));i;printf(len%d\n, len);if (i 5){break;}}}else if (pid 0){close(fd[0]);while(1){printf(给父进程%u写数据\n,getpid());write(fd[1],hello pipe,10);sleep(1);}close(fd[1]);wait(NULL);}return 0;
}综合案例 要求 : 使用代码实现 ps -A | grep bash 示例 #include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
int main(int argc, char const *argv[])
{int pd[2];pipe(pd);int pid fork();if(pid 0){printf(输入有误\n);return 0;}else if(pid 0){close(pd[1]);dup2(pd[0],0);execl(/bin/grep,/bin/grep,bash,NULL);_exit(-1);}else if(pid 0){close(pd[0]);dup2(pd[1],1);execl(/bin/ps,ps,-A,NULL);wait(NULL);}return 0;
} 有名管道
概述
又名命名管道FIFO 特点 : 1 、半双工数据在同一时刻只能在一个方向上流动。 2 、写入 FIFO 中的数据遵循先入先出的规则。 3 、 FIFO 所传送的数据是无格式的这要求 FIFO 的读出方与写入方必须事先约定好数据的格式如多少字节算一个消息等。 4 、 FIFO 在文件系统中作为一个特殊的文件而存在但 FIFO 中的内容却存放在内存中。 5 、管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。 6 、从 FIFO 读数据是一次性操作数据一旦被读它就从 FIFO 中被抛弃释放空间以便写更多的数据。 7 、当使用 FIFO 的进程退出后 FIFO 文件将继续保存在文件系统中以便以后使用。 8 、 FIFO 有名字不相关的进程可以通过打开命名管道进行通信。 概述
mkfifo函数
作用:创建有名管道
语法 #include sys/types.h #include sys/stat.h
int mkfifo(const char *pathname,mode_t mode);
参数 pathname文件名
mode文件操作模式一般使用0666所有用户可读可写
返回值 成功0 失败-1 一般失败是因为有与pathname名相同的文件
读写特点 1 、 open 打开管道 不指定 O_NONBLOCK ( 阻塞 ) 1 、 open 以只读方式打开 FIFO 时要阻塞到某个进程为写而打开此 FIFO 2 、 open 以只写方式打开 FIFO 时要阻塞到某个进程为读而打开此 FIFO 。 3 、 open 以只读、只写方式打开 FIFO 时会阻塞调用 read 函数从 FIFO 里读数据 时 read 也会阻塞。 4 、通信过程中若写进程先退出了则调用 read 函数从 FIFO 里读数据时不阻塞若写进程又重新运行则调用 read 函数从 FIFO 里读数据时又恢复阻塞。 5 、通信过程中读进程退出后写进程向命名管道内写数据时写进程也会收到 SIGPIPE 信号退出。 6 、调用 write 函数向 FIFO 里写数据当缓冲区已满时 write 也会阻塞。 2 、 open 打开管道 指定 O_NONBLOCK ( 非阻塞 ) 1 、先以只读方式打开如果没有进程 , 已经为写而打开一个 FIFO, 只读 open 成功并且 open 不阻塞。 2 、先以只写方 式打开如果没有进程 , 已经为读而打开一个 FIFO 只写 open 将出错返回-1 。 3 、 read 、 write 读写命名管道中读数据时不阻塞。 4 、通信过程中读进程退出后 写进程向命名管道内写数据时写进程也会收到SIGPIPE 信号退出。 3 、 注意 open 函数以可读可写方式打开 FIFO 文件时的特点 1 、 open 不阻塞。 2 、调用 read 函数从 FIFO 里读数据时 read 会阻塞。 3 、调用 write 函数向 FIFO 里写数据 , 当缓冲区已满时 write 也会阻塞 综合案例
09_demoA.c
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include stdlib.h
#include sys/stat.h
#include fcntl.h
#include string.h
int main(int argc, char const *argv[])
{int i 0;for(i 0;i 2;i){int pid fork();if(pid 0){break;}}if(i 0){mkfifo(./zjrtozl,0666);//张晋若发送消息int fd open(./zjrtozl,O_WRONLY);while(1){char buf[100] {0};fgets(buf,100,stdin); printf(张晋若:%s\n,buf);write(fd,buf,strlen(buf));buf[strlen(buf)-1] 0;if(strcmp(886,buf) 0){break;}}close(fd);_exit(0);}else if(i 1){mkfifo(./zltozjr,0666);//张立接收消息int fd open(./zltozjr,O_RDONLY);while(1){char buf[100] {0};read(fd,buf,sizeof(buf));printf(张立%s\n,buf);buf[strlen(buf)-1] 0;if(strcmp(886,buf) 0){break;}}close(fd);_exit(0);}else if(i 2){while(1){int pid waitpid(-1,NULL,WNOHANG);if(pid -1){break;//子进程已经回收完毕}}}return 0;
}
09_demoB.c
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include stdlib.h
#include sys/stat.h
#include fcntl.h
#include string.h
int main(int argc, char const *argv[])
{int i 0;for(i0;i 2;i){int pid fork();if(pid 0){break;}}if(i 0){mkfifo(./zltozjr,0666);//张立发消息int fd open(./zltozjr,O_WRONLY);while(1){char buf[120] {0};fgets(buf,120,stdin);printf(张立%s\n,buf);write(fd,buf,strlen(buf));buf[strlen(buf)-1] 0;if(strcmp(886,buf) 0){break;}}close(fd);_exit(0);}else if(i 1){mkfifo(./zjrtozl,0666);//张晋若接收消息int fd open(./zjrtozl,O_RDONLY);while(1){char buf[] {0};read(fd,buf,sizeof(buf));printf(张晋若%s\n,buf);buf[strlen(buf)-1] 0;if(strcmp(886,buf)0){break;}}close(fd);_exit(0);}else if(i 2){while(1){int pid waitpid(-1,NULL,WNOHANG);if(pid -1){break;//子进程回收完毕}}}return 0;
}总结
无名管道与有名管道的使用场景
1.无名管道应用于有血缘关系的进程中
2.有名管道应用于没有血缘关系的进程中
有名管道与无名管道的区别
1.无名管道是基于内存的无需文件管理系统
2.有名管道是基于文件和内存的需要文件管理系统
dup
作用;复制文件描述符
意义可以通过dup函数实现文件的重定向