一 >>>>>fork函数创建子进程:
子进程创建的过程:拷贝父进程的堆,栈,rodata段,data段,bss段,<3>fork之后父,子进程谁先执行是不确定,取决系统的调度算法
fork之后,父子进程都是从fork下一条语句开始执行
fork之后,父子进程拥有独立的4G虚拟地址空间。互相不影响
fork之后,子进程会继承父进程的打开的文件描述符集合,共享文件状态标志位和文件的偏移量。
二 >>>>>创建守护进程DAEMON:
创建子进程,父进程退出:
fork()exit();
在子进程中创建的新会话[脱离控制终端]:
setsid();
改变进程的工作目录到根目录:
chdir("");
重设文件掩码:
umask(O);
关掉不需要的文件描述符号:
close(0)close(1)close(2);
三 >>>>>线程与进程
进程只能在一个时刻干一件事,如果想同时干两件事或多件事,进程就无能为力了。
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。允许某些线程共享一部分进程的资源。一个程序的多个执行线路我们称之为线程。它也被称为轻量级别的进程。它是程序执行的最小单元。多个线程共享同一个进程的地址空间,参与系统的统一的调度。一个程序至少有一个进程,一个进程至少有一个线程。既然多个线程共享进程的地址空间。那么这个线程肯定是在进程中创建的。
四 >>>>>管理线程的函数
1、互斥锁mutex
为了实现线程间的互斥,必须在同一个线程中pthread_mutex_lock和pthread_mutex_unlock;互斥的意思是,不能同时发生,但发生的先后顺序不在乎。
2、条件变量cond
为了实现同步,同步首先是“互斥”的,同时又care先后顺序。假如一个线程获取锁之后,还要等某个条件发生(比如:sum>100),如果只用mutex,则线程大部分时间只是在lock和unlock,并且要sleep一段时间,短了浪费CPU,长了会拉长响应时间;解决办法:让线程A阻塞等待条件cond的发生(pthread_cond_wait(cond, mutex)),当线程B实现了cond时,则通知别的正在等待的线程(pthread_cond_signal(cond));
3、信号量sem
信号灯可以说是条件变量的升级版。条件变量相当于铃铛,铃铛响后每个挂起的进程还需要自己获得互斥锁并判断所需条件是否满足,信号灯把这两步操作糅合到一起。
五 >>>>>进程之间的通信
有名管道(pipe)与无名管道(mkfifo)异同点:
相同:
1.都是基于文件描述符的的进程间通信方式。2.都可以利用read(),write()函数等文件IO函数进行读写。与普通文件读写区别是管道中数据读完后就没有,数据只能读到一次。3.都不可使用lseek()进行定位操作。4.数据都是先入先出FIFO。5.读写都遵循管道读写规则。
不同:
1.无名管道只能用于具有亲缘关系的进程间通信;有名管道可用于并不相关的两个进程之间相互通信。2.无名管道通过pipe函数创建并获得操作的一对文件描述符,具有亲缘关系的进程才能使用;
而有名管道是通过mkfifo函数创建,任何进程都可以根据有名管道文件名及其所在路径利用open()函数打开,close(函数关闭,read()/write()读写。3.无名管道只在内按中有一段锻冲区,只能)疑通功pipe&救剎建并获得读写的文件描述符,而有名管道不光在内核中有一段缓冲区,而且在文件系统中有一个文件名,这个文件名对应了内核中的一段缓冲区.与普通文本文件区别在于有名管道仅仅在文件系统中有一个名字,数据是存放在内存中(内核空间)。
(摘抄){
一个房间可以认为是相对封闭不允许外人访问的,但是在某些情况下还是需要相互访问的,比如进程A执行完成后进程B才能执行,那么A需要把它执行完的事情通过某种方式告诉进程B,这就涉及到了进程间的通信,进程间通信的方式有无名管道、有名管道、信号、信号量、共享内存、消息队列、套接字。
信号是一种比较粗糙的通信方式,只是一个整数,可以有内存产生,也可以有硬件产生
信号量---semaphore与mutex类似,用于处理同步问题。我们说mutex像是一个只能容纳一个人的洗手间,那么semaphore就像是一个能容纳N个人的洗手间。其实从意义上来说,semaphore就是一个计数锁(我觉得将semaphore翻译成为信号量非常容易让人混淆semaphore与signal),它允许被N个进程获得。当有更多的进程尝试获得semaphore的时候,就必须等待有前面的进程释放锁。当N等于1的时候,semaphore与mutex实现的功能就完全相同。许多编程语言也使用semaphore处理多线程同步的问题。一个semaphore会一直存在在内核中,直到某个进程删除它。
共享内存与多线程共享global data和heap类似。一个进程可以将自己内存空间中的一部分拿出来,允许其它进程读写。当使用共享内存的时候,我们要注意同步的问题。我们可以使用semaphore同步,也可以在共享内存中建立mutex或其它的线程同步变量来同步。由于共享内存允许多个进程直接对同一个内存区域直接操作,所以它是效率最高的IPC方式。
消息队列(message queue)与PIPE相类似。它也是建立一个队列,先放入队列的消息被最先取出。不同的是,消息队列允许多个进程放入消息,也允许多个进程取出消息。每个消息可以带有一个整数识别符(message_type)。你可以通过识别符对消息分类 (极端的情况是将每个消息设置一个不同的识别符)。某个进程从队列中取出消息的时候,可以按照先进先出的顺序取出,也可以只取出符合某个识别符的消息(有多个这样的消息时,同样按照先进先出的顺序取出)。消息队列与PIPE的另一个不同在于它并不使用文件API。最后,一个队列不会自动消失,它会一直存在于内核中,直到某个进程删除该队列。}
六 >>>>>upt的服务器与客户端创建。
服务器的创建分为4步:①建立套接字———>②给struct sockaddr_in结构体赋予自身的ip和端口号——>③bind函数绑定——>④recvfrom接收别的客户端发来的信息。
客户端的创建分为3步:①建立套接字———>②给struct sockaddr_in结构体赋予目标的ip和端口号——>③sendto函数发送给目标服务器。
这里我用创建子进程的方法分布将服务端和客户端写进了一个程序里面。
以上就是我对这一周的学习的一个不太全面的总结吧,嵌入式迄今的学习对于我来说还是感受颇深的,一方面是对前面所学知识的感受,感觉学习的东西很多、知识点很杂、有很多细节的地方需要去理解、函数的用法需要理解和记忆,需要在以后的时间里时不时的去回到前面的知识点去重新看,这里的回顾不仅是把遗忘的知识捡起来,而且要在回顾的同时对以前感到困惑的地方有新的理解。另一方面是对现有的知识的应用,学习到这里,无疑是还是难度的,到现在为止对进程之间的通信方式还是存在于认识、并不能很好的去应用,很多时候在使用多时候还需要去翻阅之前的笔记,所以还是需要多去看多去练。另外,我觉的学习嵌入式,自己的编程思维还需磨练,多去做一些练习去开拓自己的思维,学习别人是怎么做的,想一想别人是怎么想到的。让自己在写代码的时候能够更加的严谨。
至此,希望能在以后的学习之中更进一步,掌握更多的知识。不要停留在幻想,坚持下去才能走得更远。