一、进程通信----共享内存
父子进程之间为例:
流程:
1. 创建共享内存
2. 创建子进程
3. 父进程中 映射内存 向内存写数据strncpy wait同步子进程
4. 子进程中 映射内存 等待父进程写入sleep 操作内存(可读)
# include < stdlib. h> # include < stdio. h> # include < string . h> # include < errno . h> # include < unistd. h> # include < sys/ stat. h> # include < sys/ types. h> # include < sys/ ipc. h> # include < sys/ shm. h> # define PERM S_IRUSR| S_IWUSR int main( int argc, char * * argv) { int shmid; char * f_addr, * c_addr; if ( argc ! = 2) { printf ( "Usage: ./shm ni hao \n" ) ; exit ( 1) ; } if ( ( shmid = shmget( IPC_PRIVATE, 1024, PERM) ) < 0) // (()())() { printf ( "shmget error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "shmget ok!\n" ) ; /* if( fork() < 0) { printf("fork error:%s\n", strerror(errno)); exit(1); }*/ if ( fork( ) ) { printf ( "father process...\n" ) ; f_addr = shmat( shmid, 0, 0) ; memset ( f_addr, '\0' , 1024) ; strncpy ( f_addr, argv[ 1] , 1024) ; printf ( "father exit!\n" ) ; wait( NULL ) ; // sleep(3); } else { sleep ( 1) ; printf ( "child process...\n" ) ; c_addr = shmat( shmid, 0, 0) ; printf ( "client get:%s\n" , c_addr) ; } }
易错点:
1.int main( int argc, char * * argv)
主函数**argv
2.if ( ( shmid = shmget( IPC_PRIVATE, 1024, PERM) ) < 0) // (()())()
先将赋值括起来,然后与0比较, 注意内存属性的描述
3. memset ( f_addr , '\0' , 1024 ) ;
映射之后,写之前要初始化内存。
4.wait ( NULL ) ;
二、 进程通信----fifo
pipe只能用父子经常之间的通信,而fifo适合任何进程之间。
流程:
1.创建fifo,以非阻塞方式打开。
说明:A:在阻塞方式下打开,(没有指定O_NONBLOCK)
(1)当以只读open是,进程阻塞,直到有进程为写而打开;
(2)当以只写open打开时,进程阻塞,直到有进程为读而打开。
B: 若指定O_NONBLOCK 方式打开
(1)若只读open 将立即返回,若只写open将出错! 所以先创建读进程,后创建写进程。
(即:在创建fifo进程,执行读,其他进程直接打开fifo后,执行写)
2.读操作
3.删除fifo文件
例: 在当前文件下创建fifo文件
fifo_read.c
# include < sys/ types. h> # include < sys/ stat. h> # include < errno . h> # include < fcntl. h> # include < stdio. h> # include < stdlib. h> # include < string . h> # define FIFO_SERVER "/tmp/myfifo" main( void ) { int fd; int read_size; char buf[ 20] ; if ( ( mkfifo( "./myfifo" , O_CREAT| O_EXCL) < 0) & & ( errno ! = EEXIST) ) // !! { printf ( "fifo creat error\n" ) ; exit ( 1) ; } printf ( "open and reading...\n" ) ; if ( ( fd = open ( "./myfifo" , O_RDONLY| O_NONBLOCK, 0) ) < 0) //creat and open in O_NONBLOCK { printf ( "open fifo:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "opened, reading ..\n" ) ; while ( 1) { memset ( buf, 0, sizeof ( buf) ) ; // 数组要初始化 if ( ( read_size = read ( fd, buf, sizeof ( buf) ) ) < 0) //use right number of () 此处一定注意!容易出错!适当的加括号 { printf ( "read error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "read %s from fifo:%d\n" , buf, read_size) ; // add '\n' in printf, or error sleep ( 1) ; //sleep, execute slowly! } pause( ) ; unlink( "./myfifo" ) ; }
程序两个容易犯错的地方:
1. if ( ( read_size = read ( fd, buf, sizeof ( buf) ) ) < 0) //use right number of ()
此处一定注意!容易出错!适当的加括号
2 .printf ( "read %s from fifo:%d\n" , buf , read_size ) ; // add '\n' in printf, or error 此处注意‘\n’别丢了
fifo_write.c
# include < sys/ types. h> # include < sys/ stat. h> # include < errno . h> # include < fcntl. h> # include < stdio. h> # include < stdlib. h> # include < string . h> # define FIFO_SERVER "/tmp/myfifo" int main( int argc, char * argv[ ] ) { int fd; char w_buf[ 20] ; int write_size; if ( ( fd= open ( "./myfifo" , O_WRONLY | O_NONBLOCK, 0) ) < 0) { printf ( "open error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "open ok\n" ) ; strcpy ( w_buf, argv[ 1] ) ; if ( ( write_size = write ( fd, w_buf, sizeof ( w_buf) ) ) < 0) { printf ( "write error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "write %s to fifo\n" , w_buf) ; close ( fd) ; return 0; }
三、
进程间通信----pipe方式
流程:1.fork创建子进程
2.pipe创建管道
3.子进程:关闭写, sleep(2)后,开始read ,关闭读。
4.父进程:关闭读,开始write, waitpid,关闭写。
# include < unistd. h> # include < errno . h> # include < stdio. h> # include < stdlib. h> main( void ) { int fd[ 2] ; pid_t child; char s[ ] = "pipe is good!" ; char buf[ 20] ; if ( pipe( fd) < 0) { printf ( "create pipe error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } if ( ( child = fork( ) ) < 0) { printf ( "fork error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } if ( 0 = = child) { close ( fd[ 1] ) ; //close another one sleep ( 2) ; // must have this printf ( "child read...\n" ) ; if ( read ( fd[ 0] , buf, sizeof ( s) ) < 0) { printf ( "read error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "\nread:%s\n" , buf) ; close ( fd[ 0] ) ; //remember to close // exit(0); // no needed } else { close ( fd[ 0] ) ; printf ( "father process:write...\n" ) ; if ( write ( fd[ 1] , s, sizeof ( s) ) < 0) { printf ( "write error:%s\n" , strerror ( errno ) ) ; exit ( 1) ; } printf ( "write ok!\n" ) ; close ( fd[ 1] ) ; waitpid( child, NULL , 0) ; // must have! compare difference form without // exit(0); // why need this? } }