Linux 多线程编程( POSIX )( 三)------->信号灯代码区—转

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");
    }

    return 0;
}
        结果:
        创建信号灯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

    return 0;
}

终端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] );            //!> 删除
   
    return 0;
}
终端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());
   
    return 0;
}
     ./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());
            return 0;
        }
    }

    wait();
    sem_close( sem );        //!> 关闭
    sem_unlink( argv[1] );        //!> 删除
    return 0;
}


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_t tid;

    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 );
   
    return 0;
}

posted @ 2012-07-31 15:40  戊辰岁终  阅读(191)  评论(0编辑  收藏  举报