转自:http://blog.sina.com.cn/s/blog_6dc9e4cf0100xdfc.html
1.sem_open与sem_close与sem_unlink与sem_getvalue
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char ** argv )
{
sem_t
*
sem;
int
val;
if( argc !=2 )
{
printf("请输入文件名!\n");
exit(EXIT_FAILURE );
}
//!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//!> 创建信号灯
if( ( sem =sem_open( argv[1], O_CREAT, 0644, 1 ) ) == SEM_FAILED )
{
//!> if 失败,报错... ...
printf("创建信号灯失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("创建信号灯OK ...\n");
}
//!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//!> 获取指定信号灯的当前值
if(sem_getvalue( sem, &val ) != 0 )
{
printf("获取值失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("获取值为VAL == %d\n", val);
}
//!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//!> 关闭信号灯
if(sem_close( sem ) != 0 )
{
printf("Close 信号灯失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("Close 信号灯OK....\n");
}
//!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//!> 删除信号灯
if(sem_unlink( argv[1] ) != 0 )
{
printf("删除信号灯失败....\n");
exit(EXIT_FAILURE );
}
else
{
printf("删除信号灯成功...\n");
}
return0;
}
结果:
创建信号灯OK...
获取值为VAL ==1
Close信号灯OK....
删除信号灯成功...
2.测试sem_close与sem_unlink不一样
//!> 测试sem_close与sem_unlink不一样
//!> 也就证明close后,再次重启一个进程还
//!> 可以访问没有删除的信号灯
//!> 创建一个名称为“shanshan”的信号灯
//!> CODE 1
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char ** argv )
{
sem_t
*
sem;
if( argc !=2 )
{
printf("请输入文件名....\n");
exit(EXIT_FAILURE );
}
if( ( sem =sem_open( argv[1], O_CREAT, 0644, 1 ) ) == SEM_FAILED)
//!> Create
{
printf("创建信号灯失败....\n");
exit(EXIT_FAILURE );
}
else
{
printf("创建信号灯OK...\n" );
}
sem_close(sem );
//!> Close
return0;
}
终端Copy:
pt@ubuntu:~/桌面/net programming/5_线程通信_POSIX_5/3_信号灯_3/CODE/测试关闭 !=删除$
./t1 shanshan
创建信号灯OK...
//!> 测试sem_close与sem_unlink不一样
//!> 也就证明close后,再次重启一个进程还
//!> 可以访问没有删除的信号灯
//!> 创建一个名称为“shanshan”的信号灯
//!> CODE 2
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char ** argv )
{
sem_t
* sem =NULL;
sem =sem_open( argv[1], 0);
//!> 打开已经创建的信号灯
//!> 没有创建哦~
if( sem&& sem != SEM_FAILED)
//!> Success
{
printf("打开已经创建的信号灯OK ...\n");
}
else
{
printf("打开已经创建的信号灯失败...\n");
exit(EXIT_FAILURE );
}
sem_close(sem );
//!> 关闭
sem_unlink(argv[1] );
//!> 删除
return0;
}
终端Copy:
pt@ubuntu:~/桌面/net programming/5_线程通信_POSIX_5/3_信号灯_3/CODE/测试关闭 !=删除$ ./t2 shanshan
打开已经创建的信号灯OK ...
//!> 注意:终端输入的参数与CODE 1应该是一样的!!!
3.sem_wait测试
//!> 创建多线程并使用sem_wait互斥
//!> 做1+2+...+10
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
int g_i = 0;
//!> 全局增量(共享变量)
int g_sum =0;
//!> 结果保存(共享变量)
sem_t
*
sem;
//!> 创建一个信号量
//!> 创建信号灯
void create_sem( char
name[] )
{
if( ( sem =sem_open( name, O_CREAT, 0644, 1 ) ) ==SEM_FAILED
)
{
printf("创建信号灯失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("创建信号灯OK....\n");
}
}
//!> 线程1入口
void * entrance_1( void * arg )
{
for( g_i =0; g_i < 11; g_i++ )
{
sem_wait(sem );
//!> 加锁
printf("线程1在执行....\n" );
g_sum +=g_i;
sem_post(sem );
//!> 解锁
sleep( 2);
}
}
//!> 线程2入口
void * entrance_2( void * arg )
{
for( g_i =0; g_i < 11; g_i++
)
{
sem_wait(sem );
//!> 加锁
printf("线程2在执行....\n" );
g_sum +=g_i;
sem_post(sem );
//!> 解锁
sleep( 3);
}
}
//!> 创建两个线程
void create_threads( pthread_t * ptid1, pthread_t * ptid2 )
{
if(pthread_create( ptid1, NULL, entrance_1, NULL ) != 0 )
{
printf("创建线程1失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("创建线程1OK ....\n");
}
if(pthread_create( ptid2, NULL, entrance_2, NULL ) != 0 )
{
printf("创建线程2失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("创建线程2OK ....\n");
}
}
//!> do and wait
void do_and_wait( pthread_t tid1, pthread_t tid2 )
{
if( tid1 !=-1 )
{
pthread_join( tid1, NULL );
}
else
{
printf("线程1错误...\n");
exit(EXIT_FAILURE );
}
if( tid2 !=-1 )
{
pthread_join( tid2, NULL );
}
else
{
printf("线程2错误...\n");
exit(EXIT_FAILURE );
}
}
//!> 关闭and删除信号灯
void close_and_del_sem( char * name )
{
if(sem_close( sem ) != 0 )
{
printf("关闭信号灯失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("关闭信号灯OK ...\n");
}
if(sem_unlink( name ) != 0 )
{
printf("删除信号灯失败...\n");
exit(EXIT_FAILURE );
}
else
{
printf("删除信号灯OK....\n");
}
}
int main( int argc, char ** argv )
{
pthread_t
tid1 =-1;
pthread_t
tid2 = -1;
//!> 创建两个线程
if( argc !=2 )
{
printf("请输入文件名!\n");
exit(EXIT_FAILURE );
}
create_sem(argv[1] );
//!> 创建信号灯
create_threads( &tid1, &tid2);
//!>创建线程
do_and_wait(tid1, tid2 );
//!> 子线程处理+等待子线程
close_and_del_sem( argv[1]);
//!> 关闭和删除信号灯
printf("子线程运行结束!\n");
printf("结果g_sum == %d\n", g_sum);
printf("我是主线程,我的 ID == %d\n", (unsigned)pthread_self());
return0;
}
./c shanshan
结果:
创建信号灯OK....
创建线程1OK....
创建线程2OK....
线程1在执行....
线程2在执行....
线程1在执行....
线程2在执行....
线程1在执行....
线程2在执行....
线程1在执行....
线程1在执行....
线程2在执行....
线程1在执行....
线程2在执行....
线程1在执行....
关闭信号灯OK...
删除信号灯OK....
子线程运行结束!
结果g_sum ==55
我是主线程,我的 ID== 927221504
4.应用Posix有名信号灯。限制访问共享代码的进程数目
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
sem_t
*
sem;
//!> 信号灯
int
val;
//!>信号灯当前值
void print_info( pid_t pid )
{
printf("我的ID== %d\n", (int)pid);
sem_getvalue( sem, &val );
printf("当前信号灯值 == %d\n", val);
}
int main( int argc, char
** argv )
{
int i =0;
if( argc !=2 )
{
printf("请输入文件名!\n");
exit(EXIT_FAILURE );
}
if(sem_open( argv[1], O_CREAT, 0644, 2 ) == SEM_FAILED)
//!> 初始化有两个可用src
{
printf("创建信号灯失败...\n");
exit(EXIT_FAILURE );
}
while( i++< 5 )
{
if( fork()0= 0 )
//!> 创建进程
{
sem_wait(sem );
//!> P 操作
print_info(getpid() );
sleep(1);
sem_post(sem );
//!> V 操作
printf("我的ID== %d, 运行结束....\n", (int)getpid());
return0;
}
}
wait();
sem_close(sem );
//!> 关闭
sem_unlink(argv[1] );
//!> 删除
return0;
}
5.应用posix基于内存的信号灯实现一个进程的各个线程间的互斥
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
sem_t
sem;
//!> 信号灯
int
value;
//!> 信号量
void * entrance( void * arg )
{
sem_wait(&sem);
//!> 计数信号灯
print_info();
sleep( 2);
sem_post(&sem);
//!> V 操作
printf("我的ID== %d, 运行结束....\n", (unsigned)pthread_self());
pthread_exit( arg );
}
void print_info()
{
printf("输出线程ID == %d\n", (unsigned)pthread_self());
sem_getvalue( &sem, &value );
printf("信号灯当前数量: %d\n", value );
}
int main( )
{
int n =0;
pthread_ttid;
if(sem_init( &sem, 0, 2 ) != 0)
//!> 线程共享,量==2
{
printf("sem_init 失败...\n");
exit(EXIT_FAILURE );
}
while( n++< 5)
//!> 创建5个线程
{
if(pthread_create( &tid, NULL, entrance, NULL ) != 0)
{
printf("创建线程%d 失败....\n", n);
exit(EXIT_FAILURE );
}
}
pthread_join( tid, NULL );
return0;
}