十四:system
int system(const char *command); //fork+exec cd /home
//命令行怎么写,它括号里就怎么写
//执行不了cd,因为fork,在子进程执行不影响父进程
功能:使用该函数可以将shell命令直接在代码中执行。
参数:command要执行的shell命令
返回值:成功 0 ,失败 -1
六:线程
一:基础定义
优点: 比多进程节省资源,可以共享变量。
概念:线程是轻量级进程,一般是一个进程中的多个任务。
进程是系统中最小的资源分配单位.
线程是系统中最小的执行单位
都能并发完成任务,
特征:1、共享资源
2、效率高 30%
3、三方库: pthread clone posix
3.1 编写代码头文件: pthread.h
3.2 编译代码加载库: -lpthread library
libpthread.so
gcc 1.c -lpthread
缺点:1,线程和进程相比,稳定性,稍微差些
2,线程的调试gdb,相对麻烦些。
info thread
*1
2
3
thread 3
二:与进程区别
1.线程属于某个进程
2.当进程运行起来后,默认有一个线程。主线程
3.线程与线程,平级。没有主次之分
4.创建的开销不同。进程3G。线程8M栈区独立
5.线程空间是共享的(除了栈区)。进程空间独立。
6.稳定性。线程弱,进程强。(线程一崩全崩)
资源:
线程比进程多了共享资源。 IPC
线程又具有部分私有资源。
进程间只有私有资源没有共享资源。
空间:
进程空间独立,不能直接通信。
线程可以共享空间,可以直接通信。
三:框架和函数s
线程的设计框架 posix:创建多线程 -->线程空间操作 -->线程资源回收
一:创建多线程pthread_create/pthread_self
int pthread_create(
pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
---------------------------------------------------------------------------------
pthread_t pthread_self(void); //获得当前线程的tid号
功能:该函数可以创建指定的一个线程。
参数:thread 线程id,需要实现定义并由该函数返回。
attr 线程属性,一般是NULL,表示默认属性。
start_routine 指向指针函数的函数指针。
本质上是一个函数的名称即可。称为th
回调函数,是线程的执行空间。
arg 回调函数的参数,即参数3的指针函数参数。
返回值:成功 0
失败 错误码
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *th1(void *arg)
{
while(1)
{
printf("send vedio tid:%lu\n",pthread_self());
sleep(1);
}
return NULL;
}
void *th2(void *arg)
{
while(1)
{
printf("receve ctrl tid:%lu\n",pthread_self());
sleep(1);
}
return NULL;
}
int main(int argc, char **argv)//主线程运行main函数
{
pthread_t tid1,tid2;
pthread_create(&tid1, NULL, th1, NULL);//线程2
pthread_create(&tid2, NULL, th2, NULL);//线程3
while(1)
{
sleep(1);//进程结束的一个条件是主线程走完程序结束,所以让他不要结束
printf("main tid:%lu \n",pthread_self());
}
//system("pause");
return 0;
}
二:线程的退出
自行退出 -->自杀 -->子线程自己退出
void pthread_exit(void *retval); exit return p;
//想要函数带回的话,直接用这个也行,不带回,参数写NULL即可
功能:子线程自行退出
参数: retval 线程退出时候的返回状态,临死遗言。
返回值:无
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* th(void* arg)
{
int i = 5;
while(i--)
{
printf("th :%lu\n",pthread_self());
sleep(1);
}
pthread_exit(NULL);//自己调用自己,自己杀自己
}
int main(int argc, char **argv)
{
pthread_t tid;
pthread_create(&tid, NULL, th, NULL);
while (1)sleep(1);
//system("pause");
return 0;
}
强制退出 ==》他杀 ==》主线程结束子线程
int pthread_cancel(pthread_t thread);
功能:请求结束一个线程
参数:thread 请求结束一个线程tid
返回值:成功 0
失败 -1;
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* th(void*arg)
{
while(1)
{
printf("th is %lu\n",pthread_self());
sleep(1);
}
pthread_exit(NULL);
//return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}
int main(int argc, char **argv)
{
pthread_t tid;
pthread_create(&tid,NULL,th,NULL);
int i = 0 ;
while(1)
{
printf("main tid:%lu, i:%d\n",pthread_self(),i);
sleep(1);
i++;
if(5 == i )
{
pthread_cancel(tid);//主函数调用,他杀,本质上都是子进程死亡
}
}
//system("pause");
return 0;
}
三:线程回收
线程的回收机制 ====》不同与进程没有孤儿线程和僵尸线程。
====》主线程结束任意生成的子线程都会结束。
====》子线程的结束不会影响主线程的运行。
int pthread_join(pthread_t thread, void **retval);
功能:通过该函数可以将指定的线程资源回收,该函数具有
阻塞等待功能,如果指定的线程没有结束,则回收线程
会阻塞。
参数:thread 要回收的子线程tid
retval 要回收的子线程返回值/状态。==》ptread_exit(值);
返回值:成功 0, 失败 -1;
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* th(void* arg)
{
int i = 5;
while (i--)
{
printf("th is %lu\n", pthread_self());
sleep(1);
}
pthread_exit(NULL);
// return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}
int main(int argc, char** argv)
{
pthread_t tid;
pthread_create(&tid, NULL, th, NULL);
pthread_join(tid, NULL);//同步 //阻塞回收。 如果th没有结束,会一直等待。如果结束,才能回收
printf("th is end\n");
// while(1)sleep(1);
// system("pause");
return 0;
}
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* th(void* arg)
{
static char buf[] = "我要消亡";//在data区,没有static,生命周期短,无法正确返回buf
// char* buf =malloc(15);
pthread_exit(buf);
// return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}
int main(int argc, char** argv)
{
pthread_t tid;
pthread_create(&tid, NULL, th, NULL);
//这个就当规范写法
void* ret = NULL;//空指针,万能指针接受
pthread_join(tid, &ret); // void** 改变指针的指向
printf("th is end,ret %s\n", (char*)ret);
return 0;
}
子线程的回收策略:
1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行则,不再回收其资源。
四:线程传参
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void *th(void *arg) {
char *tmp = (char *)arg;//让他类型一致
strcat(arg, ",wolrd");
return arg;
}
int main(int argc, char **argv)
{
char buf[1238] = "hello";
pthread_t tid;
pthread_create(&tid, NULL, th, buf);
void* ret;
pthread_join(tid, &ret);
printf("buf:%s\n",(char*)ret);
//system("pause");
return 0;
}
//结构体传参
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct {
int id;
char name[256];
} PER;
void *th(void *arg) {
PER *tmp = (PER *)arg;
printf("%d %s\n", tmp->id, tmp->name);
return NULL;
}
int main(int argc, char **argv) {
pthread_t tid;
PER per;
char buf[256] = {0};
printf("input if to per\n");
fgets(buf, sizeof(buf), stdin);
per.id = atoi(buf);
printf("input if to name\n");
fgets(per.name, sizeof(per.name), stdin);
per.name[strlen(per.name) - 1] = '\0';
pthread_create(&tid, NULL, th, &per);
pthread_join(tid, NULL);
//system("pause");
return 0;
}
int detachstate);
功能:把一个线程设置成相应的属性
参数,attr,属性变量,有init函数初始化他。
detachstate:有2个可选值,
PTHREAD_CREATE_DETACHED:设置分离属性。
int pthread_deatch(pthread_t thread);
功能,设置分离属性
参数,线程id号,填自己的id
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void *th(void *arg)
{
//方法2 。 设置分离属性 。当线程退出后,栈区由系统回收。
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv)
{
int i = 0;
for (i = 0; i < 100000; i++)
{
pthread_t tid;
int ret = pthread_create(&tid, NULL, th, NULL);//回收成功返回0
if (ret != 0)
{
break;
}
// pthread_detach(tid); 方法1
}
printf("i is %d\n", i);
// system("pause");
return 0;
}
4.1通过函数回收(两个函数类似于do - while)
void pthread_cleanup_push(void (*routine)(void *), void *arg);
功能:注册一个线程清理函数
参数,routine,线程清理函数的入口
arg,清理函数的参数。
返回值,无
void pthread_cleanup_pop(int execute);
功能:调用清理函数
execute,非0 执行清理函数
0 ,不执行清理
返回值,无
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void clean(void *arg)
{
printf("this is clean fun ,%s\n",(char*)arg);
free(arg);
}
int main(int argc, char **argv)
{
char * p = malloc(50);
pthread_cleanup_push(clean, p);
strcpy(p,"hello");
printf("main th in the ending...\n");
//system("pause");
pthread_cleanup_pop(1);
return 0;
}
五:创建多子线程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *th1(void *arg) {
printf("child tid1:%lu\n", pthread_self());
return NULL;
}
void *th2(void *arg) {
printf("child tid2:%lu\n", pthread_self());
return NULL;
}
void *th3(void *arg) {
printf("child tid3:%lu\n", pthread_self());
return NULL;
}
void *th4(void *arg) {
printf("child tid4:%lu\n", pthread_self());
return NULL;
}
void *th5(void *arg) {
printf("child tid4:%lu\n", pthread_self());
return NULL;
}
int main(int argc, char **argv) {
pthread_t tid[5];
void *(*funcs[5])(void *) = {th1, th2, th3, th4, th5};
//写成这种形式,函数指针类型,指向一个参数为 void*,返回值为 void*
//typedef void *(*ThreadFunc)(void *);
//ThreadFunc funcs[5] = {th1, th2, th3, th4, th5};
//typedef的写法
for (int i = 0; i < 5; i++) {
pthread_create(&tid[i], NULL, funcs[i], NULL);
}
while (1)
sleep(1);
// system("pause");
return 0;
}
681

被折叠的 条评论
为什么被折叠?



