用C语言编写程序建立一个pipe
c语言有名管道fifo管道的用法
c语言有名管道fifo管道的用法【C语言有名管道(FIFO管道)的用法】中括号为主题的文章【引言】C语言是一种广泛应用于系统软件开发的编程语言,拥有丰富的库函数和系统调用接口。
在C语言中,有名管道(也称为FIFO管道)是一种特殊的文件类型,用于实现不同进程之间的通信。
本文将一步一步详细介绍C语言有名管道(FIFO 管道)的用法,以帮助读者更好地理解和使用该功能。
【目录】一、什么是有名管道二、有名管道的创建三、有名管道的打开和关闭四、有名管道的读写操作五、有名管道的进程间通信六、有名管道的应用示例七、有名管道的优缺点八、总结【一、什么是有名管道】有名管道是一种特殊的文件类型,在文件系统中以文件的形式存在。
它是C语言用于进程间通信的一种方式,可以实现不同进程之间的数据传输。
有名管道是一种半双工的通信机制,允许一个进程写入数据到管道,同时另一个进程从管道中读取数据。
有名管道适用于在不相关的进程之间进行通信,特别是父子进程之间。
【二、有名管道的创建】要创建一个有名管道,首先需要使用C语言库函数mkfifo来创建一个文件节点(相当于管道的入口)。
mkfifo函数的原型如下:int mkfifo(const char *pathname, mode_t mode);其中,pathname代表要创建的有名管道的文件路径,mode用于设置管道的权限。
例如,以下代码会创建一个名为myfifo的有名管道:#include <sys/types.h>#include <sys/stat.h>int main() {mkfifo("myfifo", 0666);return 0;}运行该程序后,系统中将会被创建一个名为myfifo的有名管道。
【三、有名管道的打开和关闭】打开一个有名管道以进行读取和写入操作,可以使用C语言库函数open。
open 函数的原型如下:int open(const char *pathname, int flags);其中,pathname代表要打开的有名管道的文件路径,flags用于指定打开管道的方式(只读、只写、读写)。
Linux管道通信C语言编程示例
Linux管道通信C语⾔编程⽰例⼀、定义管道是单向的、先进先出的。
它将⼀个程序的输⼊和另⼀个程序的输出连接起来。
数据被⼀个进程读出后,将被从管道中删除。
分为⽆名和有名管道两种。
前者⽤于⽗进程和⼦进程间的通信,后者⽤于同⼀系统的两个进程间通信。
⼆、⽆名管道复制代码代码如下:int pipe(int fd[2]);其中,fd[0]⽤于读管道,fd[1]⽤于写管道。
若成功则返回零,否则返回-1,错误原因存于errno中。
三、有名管道:FIFO复制代码代码如下:int mkfifo(const char* pathname,mode_t mode)open时使⽤O_NONBLOCK,访问要求⽆法满⾜则⽴即出错返回。
erron是ENXIO。
例⼦:复制代码代码如下:fread.c //读⽂件</p> <p>#include<errno.h>#include<memory.h>#define FIFO "myfifo"main(){int fd;char buff[100];if(access(FIFO,F_OK) == -1){mkfifo(FIFO,0777);}fd=open(FIFO,O_RDONLY|O_NONBLOCK); //设置⾮阻塞打开,否则当没有输⼊时,会阻塞在read函数 </p> <p> int num; while(1){memset(buff,'\0',100); //如不清空最后的字符会出现乱码if((num=read(fd,buff,100))==0){printf("waiting.....\n");sleep(1);continue;}printf("read %d in fifo , it's %s",num,buff);sleep(1);}}</p> <p>fwrite.c //写⽂件</p> <p> </p> <p>#include<stdio.h>#include<fcntl.h>#include<memory.h>#define FIFO "myfifo"main(){int fd;char buff[100];memset(buff,'\0',100);scanf("%s",buff);if(access(FIFO,F_OK) == -1){mkfifo(FIFO,0777);}fd=open(FIFO,O_WRONLY);int num;num=write(fd,buff,strlen(buff));printf("%d char is written! It's %s\n",num,buff);}4、管道关闭:⽤close()关闭相应的⽂件描述符即可。
pipe()函数
pipe()函数介绍pipe()函数是Unix/Linux系统中一种IPC(Inter-process Communication,进程间通信)机制,用于创建一个管道(Pipe),实现父进程和子进程之间的数据通信。
管道被认为是进程间通信的最简单形式,通常被用于进程之间的数据传输和同步。
管道管道是一种半双工的数据通信方式,也就是说,同一时刻,它只能实现数据的单向传输,一端写入数据,另一端可以读出数据,但是不能同时读写数据。
管道被创建时,系统会在内存中分配一段缓冲区,用于存储数据的传输,它通常被称为“管道”,这样就可以实现进程之间的数据通信。
在Linux的文件系统中,管道被对应为一种特殊的文件类型,命名为“管道文件”,也可以被表示为“|”。
在UNIX环境下,管道是通过fork()和exec()系统调用创建的。
在C语言中,创建管道的函数是pipe(),该函数的原型如下:```cint pipe(int pipefd[2]);```该函数传递一个整型数组,用于存储两个文件描述符,分别表示管道的读端和写端。
在成功创建管道后,pipe()函数返回0,否则返回-1,表示创建管道失败。
管道的读端用于从管道中读取数据,写端用于将数据写入管道。
当读取端口被关闭时,表示管道的末端已经被关闭,写入到管道的数据在读取端口被读取后不再可用。
父进程和管道通信下面是一个简单的父子进程通信的例子。
父进程会从标准输入中读取数据,并将数据写入到管道中。
然后子进程从管道中读取数据,并将数据打印到标准输出中。
该例子中,父子进程之间使用管道进行数据通信。
```c#include <stdio.h>#include <unistd.h>#include <string.h>#define BUFSIZE 256/* 创建管道 */if (pipe(fd) < 0) {perror("pipe");return -1;}if (pid == 0) { // 子进程close(fd[1]); // 子进程关闭写端口int n = read(fd[0], buf, BUFSIZE);/* 读取父进程写入管道中的数据 */write(STDOUT_FILENO, buf, n);write(STDOUT_FILENO, "\n", 1);close(fd[0]);} else { // 父进程close(fd[0]); // 父进程关闭读端口/* 从标准输入中读取数据 */int n = read(STDIN_FILENO, buf, BUFSIZE); /* 将读取的数据写入管道 */write(fd[1], buf, n);close(fd[1]);}return 0;}```在该程序中,父进程使用write()函数向管道中写入数据,子进程使用read()函数从管道中读取数据。
linux c管道的用法
linux c管道的用法
Linux中的C管道是一种进程间通信机制,允许一个进程将其
输出连接到另一个进程的输入,从而实现数据的传输和共享。
C语言中可以使用管道来创建和操作管道。
以下是一些常见的C管道用法:
1. 创建管道:使用`pipe()`函数来创建管道。
该函数接受一个
整型数组作为参数,其中包含两个文件描述符。
第一个描述符用于读管道,第二个描述符用于写管道。
2. 管道通信:通过fork()函数创建进程后,可以使用管道进行
进程间通信。
一个进程将数据写入管道的写描述符,而另一个进程从管道的读描述符读取数据。
3. 关闭管道描述符:进程在使用完管道后,应该关闭不再需要的管道描述符。
使用`close()`函数来关闭文件描述符。
4. 重定向管道:通过dup2()函数将标准输入、标准输出或标准错误重定向到管道的输入或输出描述符。
5. 非阻塞管道:通过设置文件描述符的属性,可以将管道设置为非阻塞模式,从而避免在读取或写入管道时进程被阻塞。
6. 管道和多进程:可以使用多个管道在多个进程之间进行通信。
一个进程使用一个管道的读端和另一个进程的写端进行通信,并使用另一个管道的读端和第三个进程的写端进行通信,以此
类推。
这些是一些基本的C管道用法,还有其他更高级的用法,如
使用select()函数进行多路复用、使用匿名管道和命名管道等。
在使用C管道时,需要注意正确地打开、读取和关闭管道描
述符,并处理可能的错误。
c语言管道的用法
第二章管道一、什么是管道UNIX系统在OS的发展上,最重要的贡献之一便是该系统首创了管道(pipe)。
这也是UNIX系统的一大特色。
所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件。
由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。
句柄fd[0]句柄fd[1]读出端写入端二、管道的类型:1.有名管道一个可以在文件系统中长期存在的、具有路径名的文件。
用系统调用mknod( )建立。
它克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信。
因而其它进程可以知道它的存在,并能利用路径名来访问该文件。
对有名管道的访问方式与访问其他文件一样,需先用open( )打开。
2.无名管道一个临时文件。
利用pipe( )建立起来的无名文件(无路径名)。
只用该系统调用所返回的文件描述符来标识该文件,故只有调用pipe( )的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信。
当这些进程不再使用此管道时,核心收回其索引结点。
二种管道的读写方式是相同的,本文只讲无名管道。
3.pipe文件的建立分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符。
4.读/写进程互斥内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。
为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。
因此,每次进程在访问pipe文件前,都需检查该索引文件是否已被上锁。
若是,进程便睡眠等待,否则,将其上锁,进行读/写。
操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。
三、所涉及的系统调用1.pipe( )建立一无名管道。
系统调用格式 pipe(filedes)参数定义int pipe(filedes);int filedes[2];其中,filedes[1]是写入端,filedes[0]是读出端。
管道的一些实例代码
int main( )
{
int pfds[ 2 ];
if( pipe( pfds )==0 )
{
if( fork( )==0 )
{
close( 1 );
dup2( pfds[ 1 ],1 );
close( pfds[ 0 ] );
execlp( "ls","ls","-l",NULL );
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char* pathname,mode_t mode );创建一个命名管道
记住:管道只不过是一对文件描述符因此所有能够操作文件描述符的函数都可用于管道。这些函数
包括但不限于select,read,write,fcntl,freopen。
/*
myPipe[ 1 ]向管道写入数据;myPipe[ 0 ]从管道读取数据。
*/
int main( )
{
const char* string={"A simple message."};
int ret,myPipe[ 2 ];
char buffer[ MAX_LINE+1 ];
//create the pipe
}
else
{
close( 0 );
dup2( pfds[ 0 ],0 );
close( pfds[ 1 ] );
execlp( "wc","wc","-l",NULL );
c语言pipe函数,pipe函数(C语言)
c语⾔pipe函数,pipe函数(C语⾔)pipe我们⽤中⽂叫做管道。
以下讲解均是基于Linux为环境:函数简介所需头⽂件#include函数原型int pipe(int fd[2])函数传⼊值fd[2]:管道的两个⽂件描述符,之后就是可以直接操作者两个⽂件描述符返回值 成功0 失败-1什么是管道管道是Linux ⽀持的最初Unix IPC形式之⼀,具有以下特点:管道是半双⼯的,数据只能向⼀个⽅向流动;需要双⽅通信时,需要建⽴起两个管道; 只能⽤于⽗⼦进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成⼀种独⽴的⽂件系统:管道对于管道两端的进程⽽⾔,就是⼀个⽂件,但它不是普通的⽂件,它不属于某种⽂件系统,⽽是⾃⽴门户,单独构成⼀种⽂件系 统,并且只存在与内存中。
数据的读出和写⼊:⼀个进程向管道中写的内容被管道另⼀端的进程读出。
写⼊的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
管道的创建#includeint pipe(int fd[2])该函数创建的管道的两端处于⼀个进程中间,在实际应⽤中没有太⼤意义,因此,⼀个进程在由pipe()创建管道后,⼀般再fork⼀个⼦进程,然后通过管道实现⽗⼦进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这⾥的亲缘关系指 的是具有共同的祖先,都可以采⽤管道⽅式来进⾏通信)。
管道的读写规则管道两端可 分别⽤描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。
即⼀端只能⽤于读,由描述字fd[0]表⽰,称其为管道读端;另 ⼀端则只能⽤于写,由描述字fd[1]来表⽰,称其为管道写端。
如果试图从管道写端读取数据,或者向管道读端写⼊数据都将导致错误发⽣。
⼀般⽂件的I/O 函数都可以⽤于管道,如close、read、write等等。
从管道中读取数据:如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0; 当管道的写端存在时,如果请求的字节数⽬⼤于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数⽬不⼤于PIPE_BUF,则返回管道中 现有数据字节数(此时,管道中数据量⼩于请求的数据量);或者返回请求的字节数(此时,管道中数据量不⼩于请求的数据量)。
c++ 管道 文件读写方法
在C++ 中,可以使用管道(pipe)来实现进程间的通信,以及使用文件读写方法来读写文件。
下面分别介绍这两种方法。
一、管道(pipe)管道是一种进程间通信的方式,它允许父进程和子进程之间进行数据传输。
在C++ 中,可以使用`pipe()` 函数创建管道,并使用`read()` 和`write()` 函数进行读写操作。
下面是一个简单的示例代码,展示如何使用管道实现父子进程之间的数据传输:```c++#include <unistd.h>#include <fcntl.h>#include <iostream>int main() {int fd[2];pipe(fd); // 创建管道pid_t pid = fork(); // 创建子进程if (pid == 0) { // 子进程close(fd[0]); // 关闭管道的读端char buffer[1024];ssize_t n = read(fd[1], buffer, sizeof(buffer)); // 从管道中读取数据std::cout << "Received data: " << buffer << std::endl;exit(0);} else { // 父进程close(fd[1]); // 关闭管道的写端write(fd[0], "Hello, world!", 13); // 向管道中写入数据}return 0;}```在上面的代码中,我们首先使用`pipe()` 函数创建了一个管道,并获取了管道的文件描述符数组`fd`。
然后,我们使用`fork()` 函数创建了一个子进程,并在子进程中关闭了管道的读端,从管道中读取数据。
在父进程中,我们关闭了管道的写端,向管道中写入数据。
二、文件读写方法在C++ 中,可以使用标准库中的文件读写函数来实现文件的读写操作。
用C语言编写程序建立一个pipe
1、用C语言编写程序,建立一个pipe, 同时父进程生成一个子进程,子进程向pipe写入一个字符串”Hello.”,父进程从pipe中读取该字符串。
5'#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/wait.h>int main(){char buf[20];int piledes[2];pid_t pid;int ret;if(ret = pipe(piledes) == -1){perror("error on pipe:");exit(-1);}else{pid = fork();if(pid < 0){perror("error on fork:");exit(-1);}else if(pid == 0){close(piledes[0]);printf("to fu:");fgets(buf,sizeof(buf)-1,stdin);if((ret = write(piledes[1],buf,strlen(buf))) < 0){perror("error on writing:");exit(-1);}close(piledes[1]);}else{close(piledes[1]);if((ret = read(piledes[0],buf,sizeof(buf)-1)) < 0){perror("error on reading:");exit(-1);}buf[ret] = '\0';printf("from zi:%s\n",buf);close(piledes[0]);}}return 0;}2、编写一个 C语言程序lswc,使之功能能和ls | wc 等价。
c语言中handle的用法
c语言中handle的用法在 C 语言中,handle 是一种用于管理进程间通信的机制。
它可以用于实现进程间的同步和互斥,以及进程间的数据交换。
下面是handle 的一些用法:1. 创建 handle:使用 create_handle_map 函数可以创建handle。
该函数返回一个指向 handle_map 结构的指针,该结构包含了 handle 的信息。
2. 访问 handle:使用 map_handle 函数可以访问 handle。
该函数将一个进程的 handle 映射到另一个进程的地址空间中,从而使两个进程可以访问同一个数据结构。
3. 创建进程间通信的管道:使用 create_pipe 函数可以创建进程间通信的管道。
该函数返回一个指向 pipe_info 结构的指针,该结构包含了管道的信息。
4. 打开文件:使用 open 函数可以打开文件。
该函数返回一个指向文件描述符的指针。
可以使用 get_file_descriptor 函数获取文件描述符的 handle。
5. 使用 handle 进行进程间通信:使用 spawn 函数可以创建新进程,并在该进程中使用 create_handle_map 函数创建 handle。
然后,可以使用 map_handle 函数将 handle 映射到其他进程的地址空间中,从而实现进程间通信。
6. 销毁 handle:使用 destroy_handle_map 函数可以销毁handle。
该函数删除 handle_map 结构,并释放分配给 handle 的所有内存资源。
handle 是 C 语言中用于进程间通信的一种重要机制,它可以实现进程间的同步和互斥,以及进程间的数据交换。
使用 handle 可以提高程序的可移植性和可扩展性,使程序更加灵活和高效。
C语言创建管道实现进程间通信
C语⾔创建管道实现进程间通信#include <windows.h>#include <stdio.h>#include <stdlib.h>int runcmd( char* lpCmd ){char buf[2048] = {0}; //缓冲区DWORD len;HANDLE hRead, hWrite; // 管道读写句柄STARTUPINFO si;PROCESS_INFORMATION pi;SECURITY_ATTRIBUTES sa;//ZeroMemory( buf, 2047 );sa.nLength = sizeof( sa );sa.bInheritHandle = TRUE; // 管道句柄是可被继承的sa.lpSecurityDescriptor = NULL;// 创建匿名管道,管道句柄是可被继承的if( !CreatePipe( &hRead, &hWrite, &sa, 2048 ) ){printf( "管道创建失败!(%#X)\n", (unsigned int)GetLastError() );return1;}ZeroMemory( &si, sizeof( si ) );si.cb = sizeof( si );si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;si.wShowWindow = SW_HIDE;si.hStdError = hWrite;si.hStdOutput = hWrite;// 创建⼦进程,运⾏命令,⼦进程是可继承的if ( !CreateProcess( NULL, lpCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ) ){printf( "创建进程失败!(%#x)\n", (unsigned int)GetLastError() );CloseHandle( hRead );CloseHandle( hWrite );return1;}// 写端句柄已被继承,本地需要关闭,不然读管道时将被阻塞CloseHandle( hWrite );// 读管道内容,并显⽰while ( ReadFile( hRead, buf, 2047, &len, NULL ) ){printf( buf );ZeroMemory( buf, 2047 );}CloseHandle( hRead );return0;}int main( int argc, char** argv ){char cmd[256];printf( "输⼊命令⾏:" );gets( cmd );runcmd( cmd );system( "pause" );return0;} ⼥孩不哭(191035066)@2011-12-05 19:26:50。
c语言进程实现程序
c语言进程实现程序C语言是一种非常受欢迎的编程语言,因为它可以在Windows、Mac OS和Linux等各种平台上运行。
在C语言中,进程实现程序是实现操作系统核心的关键部分之一。
进程是计算机系统中的一个执行中的程序,每个进程都有自己的地址空间和内存分配。
在本文中,我们将分步骤阐述如何使用C语言来实现进程程序。
第一步:引入头文件在开始编写进程程序之前,需要引入C语言头文件。
C标准库的头文件可以提供很多有用的功能,比如输入/输出操作和字符串处理。
在开始编写进程程序之前,我们应该引入程序编写所需的头文件。
例如,可以使用下面的指令引入标准库头文件:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>第二步:创建进程为了创建进程,在C语言中需要使用系统调用函数fork()。
fork()函数允许父进程创建和控制子进程,从而实现在一个进程执行不同任务的目的。
以下是使用fork()创建子进程的示例:int main(int argc, char *argv[]){pid_t pid = fork();if (pid == 0){/* This is the child process. */}else if (pid > 0)/* This is the parent process. */}else{/* Error occurred while forking. */}return 0;}在上述代码中,主进程通过调用pid_t pid = fork()函数在进程空间中创建了一个子进程。
子进程和父进程都执行fork()函数调用。
如果pid为0,则说明这是子进程,如果pid大于0,则说明这是父进程。
第三步:编写子进程代码在创建子进程后,我们需要编写子进程代码,这是进程实现的关键部分。
《linux软件工程师(C语言)实用教程》第7章
14
7.2.1 信号操作的相关函数
例7.4:设计一个程序,要求程序主体运行时, 即使用户按下的中断键(Ctrl+C),也不能影响正 在运行的程序,等程序主体运行完毕后才进入 自定义信号处理函数。 源程序代码 :
15
7.2.1 信号操作的相关函数
16
7.2 管道
在Linux中,管道是一种特殊的文件,对一个进程来说,管道 的写入和读取与一个普通文件没有区别。 在Linux系统中,管道用于两个进程间的通信,这两个进程要 有同源性,即它们必须是最终由同一个进程所生成的进程。 管道通信采用的是半双工方式,即同一时间只允许单方向传 输数据。 管道是Linux支持的最初Unix IPC形式之一,具有以下特点:
38
7.4.2 系统V共享内存
shmget函数说明 shmat函数说明 shmdt函数说明
39
思考与实验
1. 设计一个程序,要求程序运行后进入一个无限循环,当 用户按下中断键(Ctrl+Z)时,进入程序的自定义信号处 理函数,当用户再次按下中断键(Ctrl+Z)后,结束程序 运行。 2. 设计一个程序,要求程序主体运行时,即使用户按下的 中断键(Ctrl+C),也不能影响正在运行的程序,等程序 主体运行完毕后才进入自定义信号处理函数。 3. 设计一个程序,要求创建一个管道PIPE,复制进程, 父进程运行命令“ls -l”,把运行结果写入管道,子进 程从管道中读取“ls -l”的结果,把读出的作为输入接 着运行“grep 7-5”。
mmap函数说明 munmap函数说明
பைடு நூலகம்
34
7.4.2 系统V共享内存
系统V共享内存指的是把所有共享数据放在共享 内存区域(IPC shared memory region),任何 想要访问该数据的进程都必须在本进程的地址 空间新增一块内存区域,用来映射存放共享数 据的物理内存页面。 系统V共享内存是通过映射特殊文件系统shm中 的文件实现进程间的共享内存通信。
C#管道式编程的介绍与实现
C#管道式编程的介绍与实现受 F# 中的管道运算符和 C# 中的 LINQ 语法,管道式编程为 C# 提供了更加灵活性的功能性编程。
通过使⽤扩展函数可以将多个功能连接起来构建成⼀个管道。
前⾔在 C# 编程中,管道式编程(Pipeline Style programming)其实存在已久,最明显的就是我们经常使⽤的 LINQ。
在进⼊ DotNetCore 世界后,这种编程⽅式就更加明显,⽐如各种中间件的使⽤。
通过使⽤这种编程⽅式,⼤⼤提⾼了代码的可维护性,优化了的业务的组合⽅式。
管道式编程具有如下优点:创建⼀个流畅的编程范例,将语句转换为表达式并将它们链接在⼀起⽤线性排序替换代码嵌套消除变量声明 - 甚⾄不需要 var提供某种形式的可变不变性和范围隔离将结构代码编写成具有明确职责的⼩ lambda 表达式......初体验基础实现在该⽰例中,我们通过构建⼀个 double->int->string 的类型转换的管道来将⼀个⽬标数据最终转化为⼀个字符串。
⾸先,我们需要定义⼀个功能接⼝,⽤于约束每个功能函数的具体实现,⽰例代码如下所⽰:public interface IPipelineStep<INPUT, OUTPUT>{OUTPUT Process(INPUT input);}然后,我们定义两个类型转换的功能类,继承并实现上述接⼝,⽰例代码如下所⽰:public class DoubleToIntStep : IPipelineStep<double, int>{public int Process(double input){return Convert.ToInt32(input);}}public class IntToStringStep : IPipelineStep<int, string>{public string Process(int input){return input.ToString();}}接着,定义⼀个扩展函数,⽤于连接上述的各个功能函数,⽰例代码如下所⽰:public static class PipelineStepExtensions{public static OUTPUT Step<INPUT, OUTPUT>(this INPUT input, IPipelineStep<INPUT, OUTPUT> step){return step.Process(input);}}最后,我们就可以构建⼀个完整的管道,⽤于我们的数据类型转换,⽰例代码如下所⽰:class Program{static void Main(string[] args){double input = 1024.1024;// 构建并使⽤管道string result = input.Step(new DoubleToIntStep()).Step(new IntToStringStep());Console.WriteLine(result);}}此时,我们成功将⼀个 double 类型的数据转化为了 string 类型。
C语言进程和进程之间通讯的方式_管道的使用
C语⾔进程和进程之间通讯的⽅式_管道的使⽤进程和进程之间的内存是相对独⽴的进程和进程通讯原理进程和进程之间通讯的⽅式管道(使⽤最简单)只能⽤在有⾎缘关系的进程之中信号(开销最⼩)共享映射区(⽆⾎缘关系)本地套接字(最稳定,实现复杂度最⾼)管道管道必须⽤在有⽗⼦关系的进程中管道是⼀种最基本的IPC机制,作⽤与有⾎缘关系的进程之间,调⽤pipe系统函数,即可以创建⼀个管道,其本质是⼀个伪⽂件(实为内核缓存区)由两个⽂件描述符引⽤,⼀个表⽰读端,⼀个表⽰写端规定数据从管道的写⼊端流⼊管道,从读取端读出局限性:⾃⼰写,不能⾃⼰读数据不可以反复读单⼯通信⾎缘关系进程间可⽤pipe函数,创建并打开管道int pipe (int fd[2]);// 参数// fd[0] : 读端// fd[1] : 写端例:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>void sys_err(const char *str){perror(str);exit(1);}int main(int agrc, char *argv[]){int ret;int fd[2];pid_t pid;char buf[1024];ret = pipe(fd);if (ret == -1){sys_err("pipe error");}pid = fork();if (pid>0){close(fd[0]); // 关闭读端write(fd[1], "hello pipe", strlen("hello pipe")); close(fd[1]);// ⽗进程} else if(pid==0){// ⼦进程close(fd[1]);ret = read(fd[0], buf, size(buf));write(STDOUT_FILENO, buf, ret);close(fd[0]);}return 0;}管道的读写⾏为读管道管道有数据,read返回实际读到的字节数管道⽆数据,⽆写端,read返回0有些端,read堵塞等待写管道⽆读端,异常终⽌有读端,管道已满,阻塞等待管道未满,返回写出的字节个数。
操作系统程序(管道铺设方案)
#include<stdio.h>#define INFINITY 9999void main(){ int a1;printf(“%46\n”,”管道铺设方案选择”);for(a1=0;a1<21;a1++)printf(“”);for(a1=0;a1<34;a1++)printf(“* *”);printf(“\n”);for(a1=0;a1<21;a1++)printf(“”);printf(“*”);printf(“欢迎使用本程序,本程序可以帮助您*”);printf(“\n”);for(a1=0;a1<21;a1++)printf(“”);printf(“*”);printf(“选择最佳管道铺设方案!*”)printf(“\n”);for(a1=0;a1<21;a1++)printf(“”);printf(“* *”);printf(“\n”);for(a1=0;a1<21;a1++)printf(“”);for(a1=0;a1<34;a1++)printf(“*”);printf(“\n”);//输入顶点个数和边得条数//system(“color 3e”);int date[20][20];int areanum;int edgnum;printf(“请输入:\n居民区个数,每个点可以的铺设路线:\n”);scanf(“%d,%d”,&areanum,&edgenum);//初始化矩阵各元素值int i,j;for(i=0;i<areanum;i++)for(“j=0;j<areanum”)date[i][j]=INFINITY;//读入边int from,to,m;printf(“输入边,格式为i,j,k, 表示i 居民点到j 居民点的距离是k(米):\n”);for(i=0;i<edgenum;i++){ scanf(“%d,%d,%d”,&from,&to,&m);date[from][to]=m;date[to][from]=m;}//输出邻接矩阵printf(”输出邻接矩阵为:\n”);for(i=0;i<areanum;i++)for(j=0;j<areanum;j++)printf(“%d\n”,date[i][j]);printf(“\n”);//prim();//辅助数组short_way,near_area//short_way[i]表示居民区I 到目前生成树中所有点集U中某个居民区(点)的路程最小值//near_way[i]表示U中能使其最小的居民区(点)int short_way[20];int mear_way[20];int min;int k,s,price;//0已经放入U中//初始化short_way 和near_wayfor(i=0;i<areanum;i++){ short_way[i]=date[0][i];near_way[i]=0;}short_way[i]=0;near_area[0]=0;s=0;printf(“从居民区0出发:\n”);for(i=0;i<areanum;i++) //有n-1条边要加入生成树,所以只要循环n-1次即可{ min=INFINITY; //求生成树外顶点到生成树内顶点具有最小权值的边j=1;k=1;while(j<areanum) //确定当前具有最小权值的边及位置{ if(short_way[j]!=0 && short_way[j]<min){ min= short_way[j];k=j;}j++;}printf(“从居民区%d到居民区%d,居民区路程(边的权值)为%d米:\n”near_area[k],k,min);short_way[k]=0;s+=min;for(j=0;j<areanum;j--){ if(date[k][j]<short_way[j]){ short_way[j]=date[k][j];near_area[j]=k;}}}printf(“%d 个居民区之间铺设煤气管道总长度最短的长度为:%d 米:\n”,areanum,s);printf(“请输入单位长度的价格(元):\n”);scanf(“%d”,&price);pringtf(“所以%d 个居民区之间铺设煤气管道最小代价为:%d 元:\n”,areanum,s*price);}。
管理管道
上一页下一节4.7.5 进程通信的实例--管道(pipe)1.管道pipe进程通信的使用例子之一是UNIX系统的管道通信。
UNIX系统从System V 开始,提供有名管道和无名管道两种通信方式,这里介绍无名管道。
无名管道为建立管道的进程及其子孙提供一条以比特流方式传送消息的通信管道。
该管道再逻辑上被看作管道文件,在物理上则由文件系统的高速缓冲区构成,而很少启动外设。
发送进程利用文件系统的系统调用write(fd[1],buf,size),把buf种的长度为size字符的消息送入管道入口fd[1],接收进程则使用系统调用read(fd[0],buf,size)从管道出口fd[0]出口读出size字符的消息置入buf中。
这里,管道按FIFO(先进先出)方式传送消息,且只能单向传送消息(如图)。
图管道通信利用UNIX提供的系统调用pipe,可建立一条同步通信管道。
其格式为:pipe(fd)int fd[2];这里,fd[1]为写入端,fd[0]为读出端。
2 .示例例1:用C语言编写一个程序,建立一个pipe,同时父进程生成一个子进程,子进向pipe中写入一字符串,父进程从pipe中读出该字符串。
解程序如下:# include <stdio.h>main(){int x, fd[2];char buf[30],s[30];pipe(fd); /*创建管道*/while((x=fork()) = = -1); /*创建子进程失败时,循环*/if(x = = 0){sprintf(buf, ”This is an example\n”);write(fd[1],buf,30); /*把buf中字符写入管道*/exit(0);}{wait(0);read(fd[0],s,30); /*父进程读管道中字符*/printf(“%s”,s);}}例2:编写一程序,建立一个管道。
同时,父进程生成子进程P1,P2,这两个进程分别向管道中写入各自的字符串,父进程读出它们(如图)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1、用C语言编写程序,建立一个pipe, 同时父进程生成一个子进程,子进程向pipe写入一个字符串”Hello.”,父进程从pipe中读取该字符串。
5'#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/wait.h>int main(){char buf[20];int piledes[2];pid_t pid;int ret;if(ret = pipe(piledes) == -1){perror("error on pipe:");exit(-1);}else{pid = fork();if(pid < 0){perror("error on fork:");exit(-1);}else if(pid == 0){close(piledes[0]);printf("to fu:");fgets(buf,sizeof(buf)-1,stdin);if((ret = write(piledes[1],buf,strlen(buf))) < 0){perror("error on writing:");exit(-1);}close(piledes[1]);}else{close(piledes[1]);if((ret = read(piledes[0],buf,sizeof(buf)-1)) < 0){perror("error on reading:");exit(-1);}buf[ret] = '\0';printf("from zi:%s\n",buf);close(piledes[0]);}}return 0;}2、编写一个 C语言程序lswc,使之功能能和ls | wc 等价。
(也就是利用,fork,exec,以及ls,wc,以及重定向,或者是管道的系统调用) 13’#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <string.h>int main(int argc,char *argv[]){int pildes[2];int ret;char *argument[3];pid_t pid;char buf[1000];if(argc < 2){printf("que shao can shu\n");exit(0);}argument[0] = "ls";argument[1] = "/";argument[2] = NULL;if((ret = pipe(pildes)) < 0){perror("error on pipe:");exit(-1);}pid = fork();if(pid <0){printf("fork error\n");exit(-1);}if(pid == 0){close(pildes[0]);dup2(pildes[1],1);execvp("ls",argument);close(pildes[1]);}else{close(pildes[1]);// dup2(fildes[0],0);if(strcmp((argv[1]),"wc") == 0){bzero(buf,sizeof(buf));if((ret = read(pildes[0],buf,sizeof(buf))) < 0){printf("error on reading:");exit(-1);}buf[ret] = '\0';printf("%s",buf);close(pildes[0]);}}return 0;}3、实现一个具有头节点的链表。
要求具有create, insert, delete, search功能,能对链表。
编写一个应用程序,使用上面的函数。
10'#include <stdio.h>#include <string.h>#include <stdlib.h>#include <error.h>#define PASSWD 111111struct student{int num;char name[20];float grade;struct student *next;};typedef struct student stuNode;typedef struct student *stuPtr;int stuwrite(stuPtr head){FILE *fp;fp = fopen("stu","w");while(head->next != NULL){head = head->next;fwrite(head,sizeof(stuNode),1,fp);}close(fp);return 0;}stuPtr sturead(){FILE *fp;stuPtr head,p1,p2;int a;head = (stuPtr)malloc(sizeof(stuNode));head->next = NULL;p1 = head;fp = fopen("stu","r");do{p2 = (stuPtr)malloc(sizeof(stuNode));p2->next = NULL;a = fread(head,sizeof(stuNode),1,fp);p1->next = p2;p1 = p2;}while(a == 1);fclose(fp);return head;}void creat(){stuPtr head,p;head = (stuPtr)malloc(sizeof(stuNode));p = (stuPtr)malloc(sizeof(stuNode));p->next = NULL;head->next = p;printf("学号:");scanf("%d",&(p->num));getchar();printf("姓名:");scanf("%s",p->name);getchar();printf("成绩:");scanf("%f",&(p->grade));getchar();stuwrite(head);}stuPtr insert(stuPtr head){stuPtr p,q;p = (stuPtr)malloc(sizeof(stuNode));printf("学号:");scanf("%d",&(p->num));getchar();printf("姓名:");scanf("%s",p->name);getchar();printf("成绩:");scanf("%f",&(p->grade));getchar();q = head;while(q->next != NULL && p->num > q->next->num) {q = q->next;}p->next = q->next;q->next = p;stuwrite(head);p = sturead();return p;}stuPtr search(stuPtr head,int num){stuPtr p1,p2;int flag;p1 = (stuPtr)malloc(sizeof(stuNode));p2 = (stuPtr)malloc(sizeof(stuNode));p1 = head;while(p1->next != NULL){flag = 0;p2 = p1;p1 = p1->next;if(p1->num == num){flag = 1;break;}}if(flag == 1){p1 = p2;return p1;}else{printf("没有此人\n");return NULL;}}stuPtr delete(stuPtr head, int num) {stuPtr p1,p2;int flag;p1 = search(head,num);p2 = p1->next;p1->next = p2->next;free(p2);stuwrite(head);p1 = sturead();return p1;}void print(stuPtr head){stuPtr p;int i;printf("学号\t姓名\t成绩\n");p = head->next;while(p != NULL){if(p->num >0 && p->grade >0){printf("%d\t%s\t%.1f\n",p->num,p->name,p->grade);}p = p->next;}}void print1(stuPtr p){printf("学号\t姓名\t成绩\n");while(p != NULL){if(p->num >0 && p->grade >0){printf("%d\t%s\t%.1f\n",p->num,p->name,p->grade);}p = p->next;}}int main(){int choose,num;stuPtr head,p;head = (stuPtr)malloc(sizeof(stuNode));p = (stuPtr)malloc(sizeof(stuNode));while(1){printf("1\t创建链表\n2\t添加节点\n3\t删除节点\n4\t查找学生\n5\t查看所有学生信息\n0\t退出\n");scanf("%d",&choose);switch(choose){case 1:creat();break;case 2:head = sturead();insert(head);break;case 3:head = sturead();printf("删除学生的学号:");scanf("%d",&num);delete(head,num);break;case 4:head = sturead();printf("学生学号:");scanf("%d",&num);p = search(head,num);p = p->next;print1(p);break;case 5:head = sturead();print(head);case 0:break;default:break;}}return 0;}。