linux中线程ptid,( 三 )代码区 - Linux 多线程编程( POSIX )_Linux编程_Linux公社-Linux系统门户网站...

Linux 多线程编程( POSIX )

( 三 )代码区

[日期:2012-03-22]

来源:Linux社区

作者:shanshanpt

[字体:大 中 小]

1.sem_open与sem_close与sem_unlink与sem_getvalue

#include

#include

#include

#include

#include

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

#include

#include

#include

#include

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

#include

#include

#include

#include

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

#include

#include

#include

#include

#include

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

#include

#include

#include

#include

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

#include

#include

#include

#include

#include

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;

}

0b1331709591d260c1c78e86d0c51c18.png

Linux创建线程有两种方式: 1. pthread_create()函数 pthread_create()函数是POSIX标准线程创建线程的函数,其函数原型如下: ```c int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); ``` 参数说明: - thread:指向线程标识符的指针 - attr:线程属性 - start_routine:线程函数的指针 - arg:传递给线程函数的参数 示例代码: ```c #include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { printf("Hello, I am a new thread!\n"); return NULL; } int main() { pthread_t tid; int ret; ret = pthread_create(&tid, NULL, thread_func, NULL); if (ret != 0) { printf("Failed to create thread!\n"); return -1; } printf("Main thread: Created a new thread (thread ID: %ld)\n", tid); pthread_exit(NULL); return 0; } ``` 2. clone()系统调用 clone()系统调用可以创建一个线程,其函数原型如下: ```c int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, .../* pid_t *ptid, void *tls, pid_t *ctid */); ``` 参数说明: - fn:线程函数指针 - child_stack:子线程的栈空间 - flags:线程创建标志 - arg:传递给线程函数的参数 示例代码: ```c #define _GNU_SOURCE #include <stdio.h> #include <sched.h> void *thread_func(void *arg) { printf("Hello, I am a new thread!\n"); return NULL; } int main() { char *stack; char *stack_top; int ret; stack = malloc(1024*1024); stack_top = stack + 1024*1024; ret = clone(thread_func, stack_top, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM, NULL); if (ret == -1) { printf("Failed to create thread!\n"); return -1; } printf("Main thread: Created a new thread (thread ID: %ld)\n", ret); return 0; } ``` 注意:clone()系统调用需要在程序定义宏#define _GNU_SOURCE才能使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值