欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > Linux线程学习

Linux线程学习

2025/4/18 21:14:39 来源:https://blog.csdn.net/2202_75840803/article/details/147075328  浏览:    关键词:Linux线程学习

一.守护进程

进程要创建会话才变成守护进程

1.守护进程的特点

后台服务进程
独立于控制终端
周期性执行某任务
不受用户登录注销影响
一般采用以d结尾的名字(服务)

2.进程组

进程的组长
        组里边的第一进程
        进程组的ID==进程中的组长的ID
进程中组长的选择
        进程中的第一个进程
进程组ID的设定
        进程组的ID就是组长的进程ID

3.会话

创建一个会话注意事项
        不能是进程组长
        创建会话的进程成为新进程组的组长
        有些lInux版本需要root权限执行此操作
        创建出的新会话丢弃原有的控制终端
        一般步骤;fork ,父亲死,儿子执行创建会话操作(setid)
获取进程所属的会话ID
        pid_t getsid(pid_t pid);
创建一个会话
        pid_t setid(void)

4.创建守护进程模型

fork子进程,父进程必须退出子进程创建新会话 必须setsid();改变当前工作目录chdir不必须如果插入一个U盘,在U盘中./a.out,拔出U盘这个文件就不在了,要想拔出U盘还行运行这个文件就要修改重设文件掩码子进程会继承父进程的掩码增加子进程程序操作的灵活性umask()不是必须的关闭文件描述符close(0)close(1)close(2)释放占用的资源不是必须的执行核心工作必须的

        

二.创建守护进程

去创建一个setsid.c文件写如下代码,父进程是结束,子进程是去使用setid函数创建一个会话,

运行结果可以看到子进程并没有运行,这印证了  “创建出的新会话丢弃原有的控制终端”

子进程它是存在的,只是脱离了终端做服务去了

ps aux可以查看到 ./a.out,这个字进程可以通过kill -9 1866 杀掉

三.线程概念

主线程和子线程
共享:
        .text
        .bss
        .data
        堆
        动态加载区
        环境变量
        命令行参数
        -通信:全局变量,堆
不共享

栈是不共享的,有几个线程分几块
一共五个线程,栈区被平均分成五块

在Linux下: 线程就是进程-轻量级进程
对于内核来货,线程就是进程
多进程和多线程的区别:
多进程: 始终共享的资源 代码、文件描述符、内存映射区--mmap
多线程:始终共享的资源:堆、全局变量,节省资源

ps aux得到下面的进程,然后去打开一个谷歌浏览器再去ps aux

发现多了很多usr

随便去ps -Lf 1982,发现,进程id都是一样的说明都是一个进程的,但是线程是不同的,线程号是给内核看的

四.线程的创建

创建线程

pthread-create()函数,

第一个参数:线程ID(指针类型要取地址)

第二个参数:NULL

第三个参数:线程要处理的函数,myfunc(自己定义的函数)

第四个参数:要传给myfunc的参数,没有NULL

1.创建线程‐‐pthread_createint pthread_create( pthread_t *thread), //线程ID = 无符号长整型const pthread_attr_t *attr, //线程属性,NULLvoid *(*start_routine)(void *), //线程处理函数void *arg); //线程处理函数参数:
pthread:传出参数,线程创建成功之后,会被设置一个合适的值attr:默认传NULLstart_routine:子线程的处理函数arg: 回调函数的参数返回值:成功:0错误:错误号 //perror不能使用该函数打印错误信息主线程先退出,子线程会被强制结束
验证线程直接共享全局变量

cd phread/  跳转到phread文件夹,如果没有可以用mkdir pthread创建这个文件夹

在pthread文件夹创建pthread_create.c

-l是一个库,-L是路径,gcc时一定要去添加一个库ld用于输出很长的内容

 去执行发现有时候子线程根本没有反应,是不是创建失败?

并不是的,线程和进程一样也是不断抢占资源的,多运行几次发行子线程它也是在运行的

主线程先退出,子线程会被强制结束

可以在主线程执行完for循环后sleep(2),这时候就会是下面的结果

线程打印错误信息

成功返回0,失败返回错误代码,去用if判断是否成功,失败就把错误号打出

返回值:成功:0错误:错误号 //perror不能使用该函数打印错误信息

错误信息是存在strerror函数中

man中strerror中介绍,其返回值是错误信息

strerror();函数中的参数就是错误号,也就是上面代码中的ret,

strerror(ret)

2.单个线程退出 --pthread_exit

进程退出用exit(0)线程用下面的函数
函数原型: void pthread_exit(void *retval);
返回可以带值,retval指针:必须指向全局,堆不带值就写NULL

在主线程的for循环前退出线程,发现执行完子线程后就退出了,pthread_exit函数是可以单一退出线程,列如在子线程中使用这个函数,他就会退出子线程,主线程是继续运行的。如果在子线程中用exit函数是会连同主线程一起退出,因为它是退出整个进程。

pthread_exit(NULL)与return NULL一样。

3.阻塞等待线程退出,获取线程退出状态--pthread_join

函数原型:
int pthread_join(pthread_t pthread, void **retval)
参数:pthread:要回收的子线程的IDretval:读取线程退出的携带信息二级指针**retval指向的是上一个函数pthread_exit()的*retval指针地址例如:int num;pthread_exit(&num);这时**retual就是指向num如何定义**retval?传出参数void* ptr;pthread_join(pthid,&ptr);指向的内存和pthread_exit参数指向地址一致

下面代码定义的num是函数内部的局部变量,函数是要求是全局变量或堆,所以打印出的数是随机值,

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词