一、进程通信----共享内存
父子进程之间为例:
流程:
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?
}
}