客户端和服务端是进程
html
命名机制 传送机制
TCP是一个构建在IP之上的复杂协议,提供了进程间可靠地全双工链接
linux
对inet-aton的调用传递的是指向结构的指针,而对inet_ntoa的调用传递的是结构自己git
某些合法域名没有映射到任何IP地址程序员
套接字地址:(地址:端口)
web
sin_family成员是AF_INET sin_port成员是一个16位端口 sin_addr成员是32位的IP地址
客户端和服务端使用socket函数来建立一个套接字描述符编程
创建和服务器的链接。数组
将socket和connect函数包装而成。客户端能够用它来和服务器创建链接。浏览器
告诉内核将my_addr中的服务器套接字地址和套接字描述符sockfd联系起来安全
将sockfd从一个主动套接字转化为一个监听套接字服务器
均被服务器用于和客户端创建链接。
socket、bind和listen函数结合。用于服务器建立一个监听描述符。
Web内容能够用一种叫作 HTML(Hypertext Markup Language,超文本标记语言)的语言来编写。一个 HTML 程序(页)包含指令(标记),它们告诉浏览器如何显示这页中的各类文本和图形对象。
每条由Web服务器返回的内容都是和他管理的某个文件相关联的。这些文件每个都有一个惟一的名字,叫作:URL
进程 I/O多路复用 线程
第一步:服务器接受客户端的链接请求 第二步:服务器派生一个子进程为这个客户端服务 第三步:服务器接受另外一个链接请求 第四步:服务器派生另外一个子进程为新的客户端服务
最后,知道父子进程的connfd都关闭了,到客户端的链接才会终止
优势:一个进程不可能不当心覆盖另外一个进程的虚拟存储器 缺点:独立的地址空间使得进程共享信息变得更加困难;IPC机制每每比较慢
分配 将一个此种类型的变量赋值给另外一个变量 用FD_ZERO、FD_SET等宏指令来修改和检查它们
状态:等待描述符dk准备好可读 输入事件:描述符dk准备好能够读了 转移:从描述符dk读一个文本行
check_clients:为准备好的客户端链接服务
缺点:编码复杂
每一个对等线程都能读写相同共享数据
现成的代码和本地数据被封装在一个线程例程中
新线程能够经过调用pthread_self函数来得到它本身的线程ID
另外一个对等线程经过调用pthread_cancle函数来终止当前线程
与wait函数不一样,pthread_join函数只能等待一个指定的线程终止
pthreaddetach 函数分离可结合线程 tid. 线程可以经过以 pthreadself()为参数的 pthread_detach 调用来分离它们本身。
once_control变量是一个全局或者静态变量
调用 pthread_ create 时,如何将已链接描述符传递给对等线程。最明显的方法就是传递一个指向这个描述符的指针。 对等线程间接引用这个指针,并将它赋值给一个局部变量。
若是一个线程以某种方式获得一个指向其余线程栈的指针,那么它就能够读写这个栈的任何部分
本地静态变量:本地静态变量是定义在函数内部有static属性的变量
msgs这样的本地自动变量也能被共享
合法的转换是向右或者向上,即某一个线程中的一条指令完成 两条指令不能在同一时刻完成,即不容许出现对角线 程序不能反向运行,即不能出现向下或向左 而一个程序的执行历史被模型化为状态空间中的一条轨迹线。 线程循环代码的分解: H:在循环头部的指令块 L:加载共享变量cnt到线程i中寄存器%eax的指令。 U:更新(增长)%eax的指令 S:将%eax的更新值存回到共享变量cnt的指令 T:循环尾部的指令块
安全轨迹线:绕开不安全区的轨迹线
P(s):若是s是非零的,那么P将s-1,而且当即返回;若是s为零,那么就挂起这个线程,直到s变为非零 V(s):V操做将s+1
信号量不变性:一个正在运行的程序毫不能进入这样一种状态,也就是一个正确初始化了的信号量有一个负值。
计数信号量:一个呗用做一组可用资源的计数器的信号量
pthread_creat:建立线程,若成功则返回0,若失败则返回出错编号。第一个参数为指向线程标识符的指针,建立成功时指向的内存单元被设置为新建立线程的线程ID;第二个参数设置线程属性;第三个参数是线程运行函数的起始地址;最后一个参数是运行函数的参数 pthread_join:用来等待一个线程的结束。当函数返回时,被等待线程的资源被收回。 pthread_mutex_lock:线程调用该函数让互斥锁上锁。成功锁定时返回0,其余任何返回值都表示出现了错误。 pthread_mutex_unlock:与pthread_mutex_lock成对存在。释放互斥锁。
主函数中用srand(time(NULL))
设置当前的时间值为种子,在后面的producer和consumer函数中调用rand()函数产生随机数。
mmap函数 `void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);` 将一个文件或者其余对象映射进内存。文件被映射到多个页上,若是文件的大小不是全部页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中做用很大。 成功执行时,mmap()返回被映射区的指针,munmap()返回0.失败时,mmap()返回MAP_FAILED,munmap返回-1.
lseek函数 off_t lseek(int fd,off_t offset,int whence); fd表示要操做的文件描述符,offset是相对于whence(基准)的偏移量,whence能够是SEEK_SET(文件指针开始),SEEK_CUR(文件指针当前位置),SEEK_END(文件指针尾) lseek主要做用是移动文件读写指针,返回文件读写指针距文件开头的字节大小,若出错则返回-1.
运行结果
主函数中先利用pthread_create()函数建立一个线程,接着调用printids函数(打印标识符的函数)打印主线程号,最后线程函数thr_fn中打印出新建的线程号
-lm
,能够成功编译,运行结果提示了段错误。1)访问系统数据区,尤为是往 系统保护的内存地址写数据 最多见就是给一个指针以0地址 2)内存越界(数组越界,变量类型不一致等 3)访问到不属于你的内存区域
阅读代码后仍没找到错误,问题还没有解决。
sem_init函数 sem_init(sem_t *sem, int pshared, umsigned int value); 函数初始化一个定位在sem的匿名信号量;pshared参数为0指明信号量是由进程内线程共享,若为非0值则信号量在进程之间共享;value参数指定信号量的初始值。 sem_init()成功时返回0;错误时返回-1,并把errno设置为合适的值。 sem_destroy()函数用于销毁由sem指向的匿名信号量。只有经过sem_init()初始化的信号量才应该使用该函数销毁。函数成功时返回0,错误时返回-1,并把errno设置为合适的值。 这个函数和以前的condvar.c同样都是展现生产者和消费者交替工做的过程。区别是本程序实现生产或消费的过程是利用sem_wait()和sem_post(),它们的做用分别是从信号量的值减去一个“1”和从信号量的值加上一个“1”
运行结果截图
代码运行结果以下
修改后代码运行以下
代码运行结果以下
根据代码,先单独执行print_msg("hello");——输出5个hello,后输出5个带换行的world
因为定义中NUM=5,因此输出的count为1——5
twordcount4.c运行以下
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 200/400 | 2/4 | 18/38 | |
第三周 | 100/500 | 1/5 | 10/48 | |
第四周 | 250/750 | 1/6 | 10/58 | |
第五周 | 100/850 | 1/7 | 10/68 | |
第六周 | 100/950 | 1/8 | 12/80 | |
第七周 | 200/1150 | 1/9 | 12/92 | |
第八周 | 124/1274 | 2/11 | 10/102 | |
第九周 | 205/1479 | 2/13 | 5/107 | |
第十周 | 646/2125 | 2/15 | 9/116 | |
第十一周 | 421/2546 | 2/17 | 12/128 | |
第十二周 | 752/3298 | 3/10 | 11/139 | |
第十三周 | 1001/4299 | 1/21 | 12/151 |