本篇文章给大家谈谈pthread与PHP7.0.8,以及ZTS的知识点,同时本文还将给你拓展c中pthread与线程的优点、c++多线程编程之CreateThread与_beginthreadex本质
本篇文章给大家谈谈pthread与PHP 7.0.8,以及ZTS的知识点,同时本文还将给你拓展c 中pthread与线程的优点、c++多线程编程之CreateThread与_beginthreadex本质区别、checking for ZTS... configure: error: pthreads requires ZTS, please re-compile PHP with ZTS enabled、gcc 4.7在Linux pthreads – 非常规thread_local解决方法使用__thread(没有提升)等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:- pthread与PHP 7.0.8(ZTS)
- c 中pthread与线程的优点
- c++多线程编程之CreateThread与_beginthreadex本质区别
- checking for ZTS... configure: error: pthreads requires ZTS, please re-compile PHP with ZTS enabled
- gcc 4.7在Linux pthreads – 非常规thread_local解决方法使用__thread(没有提升)
pthread与PHP 7.0.8(ZTS)
我想用PHP 7.0.8(ZTS)(手动编译和configuration)使用pthreads我已经在编译PHP时添加followinGconfiguration:
--enable-maintainer-zts --enable-pthreads=shared --with-tsrm-pthreads
注意:fpm正在运行,pid 25546
注意:准备处理连接
我使用pecl: pecl install pthreads-3.1.6添加pthread扩展,并将extension = pthreads.so添加到我的PHP.ini中。 但重启PHP7-fpm后,PHP-fpm没有运行:
在Linux上最好的沙盒Apache方法
在XDEBUG中出错
无限滚动从默认的Linux命令行
apt-get返回错误“debconf:Perl可能是未configuration的”/我如何真正理解linux错误
如何在Debian上卸载xdebug?
注意:正在完成…
注意:退出,再见!
我有一个502 Nginx错误。
如何在PHP.ini中添加这个扩展名而不退出PHP-fpm?
为什么HTOP在正常运行时间旁边显示惊叹号
我在哪里可以find并安装pygame的依赖关系?
在terminal窗口中启动文件pipe理器
将虚拟接口的IP地址绑定到ftp客户端
PHP驱动程序DataStax Cassandra DB – 如何使用?
你应该使用PHP-cli来使用pthreads。 您可以为CLI创建第二个PHP.ini配置:
首先,如果不存在你的PHP.ini文件到PHP-cli.ini:
cp /PATH_OF_YOUR_PHP_INSTALLATION/PHP.ini /PATH_OF_PHP_INSTALLATION/PHP-cli.ini
然后,使用PECL安装pthreads(如果PHP是使用--enable-maintainer-zts --enable-pthreads=shared --with-tsrm-pthreads )
pecl install pthreads
然后,将扩展的配置添加到您的PHP-cli.ini中:
echo "extension=/PATH_OF_EXTENSION/pthreads.so" >>/PATH_OF_PHP_INSTALLATION/PHP-cli.ini
Finnaly,重新启动你的PHP7-fpm服务:
service PHP7-fpm restart
您可以测试pthread安装是否正在创建一个测试类并使用PHP执行它:创建文件:ImportWorker.PHP
<?PHP class ImportWorker extends Worker { private $data; public function __construct($_data) { $this->data = $_data;// } public function run(){ var_dump("Worker test"); } }
执行: PHP ImportWorker.PHP – >如果你有任何错误,那是pthreads不起作用。
总结
以上是小编为你收集整理的pthread与PHP 7.0.8(ZTS)全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
c 中pthread与线程的优点
我见过使用pthread编写C语言和使用线程库的其他代码的多线程程序的代码.使用线程库而不是ptheard有什么好处?
解决方法
>它是跨平台的.例如,默认情况下,pthreads库在Windows上不可用.使用线程保证将使用可用的实现.> C线程强制执行正确的行为.例如,尝试破坏未连接,未分离的线程的句柄会导致程序中止.这是一件非常好的事情,因为它让人们意识到他们在做什么.> C线程完全合并到C语言中.您不再需要在某种结构中分配您的参数,并将此结构的地址作为void *传递给您的pthread例程.通过使用可变参数模板,C线程库允许您向线程启动例程提供任意数量的参数,并为您进行类型检查.> C线程有一组很好的周围类,比如promise.现在你可以从线程中抛出异常,而不会导致整个程序崩溃!
c++多线程编程之CreateThread与_beginthreadex本质区别
使用多线程其实是非常容易的,下面这个程序的主线程会创建了一个子线程并等待其运行完毕,子线程就输出它的线程ID号然后输出一句经典名言——Hello World。整个程序的代码非常简短,只有区区几行。
//最简单的创建多线程实例
#include <stdio.h>
#include <windows.h>
//子线程函数
DWORD WINAPI ThreadFun(LPVOID pM)
{
printf("子线程的线程ID号为:%d\n子线程输出Hello World\n", GetCurrentThreadId());
return 0;
}
//主函数,所谓主函数其实就是主线程执行的函数。
int main()
{
printf(" 最简单的创建多线程实例\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
HANDLE handle = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
WaitForSingleObject(handle, INFINITE);
return 0;
}
下面来细讲下代码中的一些函数
第一个 CreateThread
函数功能:创建线程
函数原型:
HANDLEWINAPICreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes,
SIZE_TdwStackSize,
LPTHREAD_START_ROUTINElpStartAddress,
LPVOIDlpParameter,
DWORDdwCreationFlags,
LPDWORDlpThreadId
);
函数说明:
第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。
第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数是传给线程函数的参数。
第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
函数返回值:
成功返回新线程的句柄,失败返回NULL。
第二个 WaitForSingleObject
函数功能:等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。
函数原形:
DWORDWINAPIWaitForSingleObject(
HANDLEhHandle,
DWORDdwMilliseconds
);
函数说明:
第一个参数为要等待的内核对象。
第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。
因为线程的句柄在线程运行时是未触发的,线程结束运行,句柄处于触发状态。所以可以用WaitForSingleObject()来等待一个线程结束运行。
函数返回值:
在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED
CreateThread()函数是Windows提供的API接口,在C/C++语言另有一个创建线程的函数_beginthreadex(),在很多书上(包括《Windows核心编程》)提到过尽量使用_beginthreadex()来代替使用CreateThread(),这是为什么了?下面就来探索与发现它们的区别吧。
首先要从标准C运行库与多线程的矛盾说起,标准C运行库在1970年被实现了,由于当时没任何一个操作系统提供对多线程的支持。因此编写标准C运行库的程序员根本没考虑多线程程序使用标准C运行库的情况。比如标准C运行库的全局变量errno。很多运行库中的函数在出错时会将错误代号赋值给这个全局变量,这样可以方便调试。但如果有这样的一个代码片段:
if (system("notepad.exe readme.txt") == -1)
{
switch(errno)
{
...//错误处理代码
}
}
假设某个线程A在执行上面的代码,该线程在调用system()之后且尚未调用switch()语句时另外一个线程B启动了,这个线程B也调用了标准C运行库的函数,不幸的是这个函数执行出错了并将错误代号写入全局变量errno中。这样线程A一旦开始执行switch()语句时,它将访问一个被B线程改动了的errno。这种情况必须要加以避免!因为不单单是这一个变量会出问题,其它像strerror()、strtok()、tmpnam()、gmtime()、asctime()等函数也会遇到这种由多个线程访问修改导致的数据覆盖问题。
为了解决这个问题,Windows操作系统提供了这样的一种解决方案——每个线程都将拥有自己专用的一块内存区域来供标准C运行库中所有有需要的函数使用。而且这块内存区域的创建就是由C/C++运行库函数_beginthreadex()来负责的。下面列出_beginthreadex()函数的源代码(我在这份代码中增加了一些注释)以便读者更好的理解_beginthreadex()函数与CreateThread()函数的区别。
//_beginthreadex源码整理By MoreWindows( http://blog.csdn.net/MoreWindows )
_MCRTIMP uintptr_t __cdecl _beginthreadex(
void *security,
unsigned stacksize,
unsigned (__CLR_OR_STD_CALL * initialcode) (void *),
void * argument,
unsigned createflag,
unsigned *thrdaddr
)
{
_ptiddata ptd; //pointer to per-thread data 见注1
uintptr_t thdl; //thread handle 线程句柄
unsigned long err = 0L; //Return from GetLastError()
unsigned dummyid; //dummy returned thread ID 线程ID号
// validation section 检查initialcode是否为NULL
_VALIDATE_RETURN(initialcode != NULL, EINVAL, 0);
//Initialize FlsGetValue function pointer
__set_flsgetvalue();
//Allocate and initialize a per-thread data structure for the to-be-created thread.
//相当于new一个_tiddata结构,并赋给_ptiddata指针。
if ( (ptd = (_ptiddata)_calloc_crt(1, sizeof(struct _tiddata))) == NULL )
goto error_return;
// Initialize the per-thread data
//初始化线程的_tiddata块即CRT数据区域 见注2
_initptd(ptd, _getptd()->ptlocinfo);
//设置_tiddata结构中的其它数据,这样这块_tiddata块就与线程联系在一起了。
ptd->_initaddr = (void *) initialcode; //线程函数地址
ptd->_initarg = argument; //传入的线程参数
ptd->_thandle = (uintptr_t)(-1);
#if defined (_M_CEE) || defined (MRTDLL)
if(!_getdomain(&(ptd->__initDomain))) //见注3
{
goto error_return;
}
#endif // defined (_M_CEE) || defined (MRTDLL)
// Make sure non-NULL thrdaddr is passed to CreateThread
if ( thrdaddr == NULL )//判断是否需要返回线程ID号
thrdaddr = &dummyid;
// Create the new thread using the parameters supplied by the caller.
//_beginthreadex()最终还是会调用CreateThread()来向系统申请创建线程
if ( (thdl = (uintptr_t)CreateThread(
(LPSECURITY_ATTRIBUTES)security,
stacksize,
_threadstartex,
(LPVOID)ptd,
createflag,
(LPDWORD)thrdaddr))
== (uintptr_t)0 )
{
err = GetLastError();
goto error_return;
}
//Good return
return(thdl); //线程创建成功,返回新线程的句柄.
//Error return
error_return:
//Either ptd is NULL, or it points to the no-longer-necessary block
//calloc-ed for the _tiddata struct which should now be freed up.
//回收由_calloc_crt()申请的_tiddata块
_free_crt(ptd);
// Map the error, if necessary.
// Note: this routine returns 0 for failure, just like the Win32
// API CreateThread, but _beginthread() returns -1 for failure.
//校正错误代号(可以调用GetLastError()得到错误代号)
if ( err != 0L )
_dosmaperr(err);
return( (uintptr_t)0 ); //返回值为NULL的效句柄
}
讲解下部分代码:
注1._ptiddataptd;中的_ptiddata是个结构体指针。在mtdll.h文件被定义:
typedefstruct_tiddata * _ptiddata
微软对它的注释为Structure for each thread''s data。这是一个非常大的结构体,有很多成员。本文由于篇幅所限就不列出来了。
注2._initptd(ptd, _getptd()->ptlocinfo);微软对这一句代码中的getptd()的说明为:
/* return address of per-thread CRT data */
_ptiddata __cdecl_getptd(void);
对_initptd()说明如下:
/* initialize a per-thread CRT data block */
void__cdecl_initptd(_Inout_ _ptiddata _Ptd,_In_opt_ pthreadlocinfo _Locale);
注释中的CRT (C Runtime Library)即标准C运行库。
注3.if(!_getdomain(&(ptd->__initDomain)))中的_getdomain()函数代码可以在thread.c文件中找到,其主要功能是初始化COM环境。
由上面的源代码可知,_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread()。相信阅读到这里时,你会对这句简短的话有个非常深刻的印象,如果有面试官问起,你也可以流畅准确的回答了^_^。
接下来,类似于上面的程序用CreateThread()创建输出“Hello World”的子线程,下面使用_beginthreadex()来创建多个子线程:
//创建多子个线程实例
#include <stdio.h>
#include <process.h>
#include <windows.h>
//子线程函数
unsigned int __stdcall ThreadFun(PVOID pM)
{
printf("线程ID号为%4d的子线程说:Hello World\n", GetCurrentThreadId());
return 0;
}
//主函数,所谓主函数其实就是主线程执行的函数。
int main()
{
printf(" 创建多个子线程实例 \n");
printf(" -- by MoreWindows(
http://blog.csdn.net/MoreWindows
) --\n\n");
const int THREAD_NUM = 5;
HANDLE handle[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++)
handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
return 0;
}
图中每个子线程说的都是同一句话,不太好看。能不能来一个线程报数功能,即第一个子线程输出1,第二个子线程输出2,第三个子线程输出3,……。要实现这个功能似乎非常简单——每个子线程对一个全局变量进行递增并输出就可以了。代码如下:
//子线程报数
#include <stdio.h>
#include <process.h>
#include <windows.h>
int g_nCount;
//子线程函数
unsigned int __stdcall ThreadFun(PVOID pM)
{
g_nCount++;
printf("线程ID号为%4d的子线程报数%d\n", GetCurrentThreadId(), g_nCount);
return 0;
}
//主函数,所谓主函数其实就是主线程执行的函数。
int main()
{
printf(" 子线程报数 \n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
const int THREAD_NUM = 10;
HANDLE handle[THREAD_NUM];
g_nCount = 0;
for (int i = 0; i < THREAD_NUM; i++)
handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
return 0;
}
checking for ZTS... configure: error: pthreads requires ZTS, please re-compile PHP with ZTS enabled
安装多线程“ pthreads”时,出现了一个这样的error错误:
checking for ZTS... configure: error: pthreads requires ZTS, please re-compile PHP with ZTS enabled
翻译成中文
检查ZTS…配置:错误:Pthreads需要ZTS,请重新编译PHP ZTS启用
ZTS解决办法:
只需要在PHP编译参数基础上加上:--enable-maintainer-zts 即可!
注意:zts不能动态加载,必须PHP源码编译加载,因此:千万不要产生不需要编译PHP就能解决这个问题的错误想法。
看到大多数,都是要求重新编译PHP,如果你有更好的办法,欢迎留言交流.
本文同步分享在 博客“lxw1844912514”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
gcc 4.7在Linux pthreads – 非常规thread_local解决方法使用__thread(没有提升)
在C ++ 11中,可以使用thread_local存储来创build一个非平凡的对象:
class X { ... } void f() { thread_local X x = ...; ... }
不幸的是,这个function还没有在gcc中实现(从4.7开始)。
海湾合作委员会确实允许你有线程局部variables,但只有琐碎的types。
我正在寻找一个解决方法:
当一个二进制文件运行时,它是否将其整个二进制数据一次性复制到内存中? 我可以改变吗?
libusb-1.0 hotplug事件在fork()之后在parent中停止工作,当child调用libusb_exit()
如何通过蓝牙从iPhone / iPod Touch发送stream数据到Windows C ++应用程序?
执行时间:GetFrontBufferData,GetBackBuffer,GetrendertargetData
该进程无法访问该文件,因为它正在被另一个进程使用
这是我到目前为止:
#include <iostream> #include <type_traits> using namespace std; class X { public: X() { cout << "X::X()" << endl; }; ~X() { cout << "X::~X()" << endl; } }; typedef aligned_storage<sizeof(X),alignment_of<X>::value>::type XStorage; inline void placement_delete_x(X* p) { p->~X(); } void f() { static __thread bool x_allocated = false; static __thread XStorage x_storage; if (!x_allocated) { new (&x_storage) X; x_allocated = true; // Todo: add thread cleanup that // calls placement_delete_x(&x_storage) } X& x = *((X*) &x_storage); } int main() { f(); }
我需要帮助的是在当前线程退出时调用placement_delete_x(&x_storage)。 有没有一种机制在pthreads和/或linux我可以用来做到这一点? 我需要添加一个函数指针和一个参数的某种pthread清理堆栈?
更新:
我认为pthread_cleanup_push可能是我想要的:
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cleanup_push.3.html
这是否会在正确的情况下调用清理处理程序?
更新2:
它看起来像boost::thread_specific_ptr最终调用pthread_key_create destructor参数,而不是pthread_cleanup_push – 调用它的tls清理function:
http://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_key_create.html
目前还不清楚这两种方法之间有什么区别,如果有的话。 ?
如何在命令行的语言环境中显示文本?
在Linux上堆栈溢出沉默?
Cygwin编译错误:“这个应用程序已经请求运行时以不寻常的方式终止它”
GetSysColorBrush常数的选项卡控件的背景颜色?
为什么这个循环会毁掉我的记忆?
pthread_key_create和朋友是你想要使用析构函数实现线程特定的类型变量。 但是,这些通常需要您管理创建和销毁变量的整个过程,我不确定是否可以将它们与__thread结合使用。
pthread_cleanup_push不适合。 如果线程在使用该资源的(短)代码块期间退出,则允许释放资源; 如链接到的文档中所述,它必须与该函数的同一级别的pthread_cleanup_pop匹配,并且如果线程从其主函数返回,则不会调用该处理程序。 这意味着如果你希望线程局部变量在对函数的调用之间保持不变,就不能使用它。
对于那些不禁止使用第三方库的人来说, Boost提供了一种便捷的方式来管理线程本地存储。
正如Mike所说, pthread_cleanup_push不合适。 正确的方法是使用pthread_key_create 。
我已经实现了一个小的演示程序来演示如何做到这一点。 我们实现一个像这样使用的宏thread_local :
有了真正的C ++ 11功能,它将是:
void f() { thread_local X x(1,2,3); ... }
这是它:
void f() { thread_local (X,x,1,3); ... }
这个和boost :: thread_specifc_ptr之间的区别在于没有动态内存分配。 所有内容都以__thread持续时间存储。 它也明显更轻,但它是特定于gcc / linux的。
概述:
我们使用std::aligned_storage为变量创建__thread持续时间空间
在给定线程的第一个条目中,我们使用placement new来构造存储中的变量
我们还__thread分配一个链接列表条目的位置删除调用
我们使用pthread_setspecific来跟踪每个线程列表头
传递给pthread_key_create的函数pthread_key_create线程退出时调用位置的列表。
…
#include <iostream> #include <thread> using namespace std; static pthread_key_t key; static pthread_once_t once_control = PTHREAD_ONCE_INIT; struct destructor_list { void (*destructor)(void*); void* param; destructor_list* next; }; static void execute_destructor_list(void* v) { for (destructor_list* p = (destructor_list*) v; p != 0; p = p->next) p->destructor(p->param); } static void create_key() { pthread_key_create(&key,execute_destructor_list); } void add_destructor(destructor_list* p) { pthread_once(&once_control,create_key); p->next = (destructor_list*) pthread_getspecific(key); pthread_setspecific(key,p); } template<class T> static void placement_delete(void* t) { ((T*)t)->~T(); } #define thread_local(T,t,...) T& t = *((T*) ({ typedef typename aligned_storage<sizeof(T),alignment_of<T>::value>::type Storage; static __thread bool allocated = false; static __thread Storage storage; static __thread destructor_list dlist; if (!allocated) { new (&storage) T(__VA_ARGS__); allocated = true; dlist.destructor = placement_delete<T>; dlist.param = &storage; add_destructor(&dlist); } &storage; })); class X { public: int i; X(int i_in) { i = i_in; cout << "X::X()" << endl; }; void f() { cout << "X::f()" << endl; } ~X() { cout << "X::~X() i = " << i << endl; } }; void g() { thread_local(X,1234); xf(); } int main() { thread t(g); t.join(); }
笔记:
您需要为每个pthread_ *调用添加错误检查。 我刚刚删除它的说明。
它使用__thread这是一个GNU扩展
它使用表达式语句将辅助__thread变量名称保留在父范围之外。 这也是一个GNU扩展。
今天关于pthread与PHP 7.0.8和ZTS的讲解已经结束,谢谢您的阅读,如果想了解更多关于c 中pthread与线程的优点、c++多线程编程之CreateThread与_beginthreadex本质区别、checking for ZTS... configure: error: pthreads requires ZTS, please re-compile PHP with ZTS enabled、gcc 4.7在Linux pthreads – 非常规thread_local解决方法使用__thread(没有提升)的相关知识,请在本站搜索。
本文标签: