10 2011 档案

摘要:昨天看了下线程池,虽然原理什么都比较好理解,但是实现起来感觉自己的方法还是非常笨。这里没直接把任务也做了一个池,就不用动态的分配操作了。下面是代码以及测试:#include <pthread.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#define MAX_THREAD_NUM 100#define MAX_WORK_NUM 1000struct gwork{ void (*f 阅读全文
posted @ 2011-10-29 19:14 GG大婶 阅读(1551) 评论(4) 推荐(0)
摘要:单例模式用来创建独一无二的对象。有些类型比如驱动程序等只能有一个对象,如果创建出多个对象的时候可能会导致许多问题的产生。单例模式还是很简单的,实现方法也很多,不过需要注意并发的情况。下面是一个简单的例子(非并发):class singleton{ private static singleton single; private singleton(){ } public singleton getSigle(){ if(single == null){ single = new singleton(); ... 阅读全文
posted @ 2011-10-29 17:11 GG大婶 阅读(205) 评论(0) 推荐(0)
摘要:1、数据的存储 虽然从Ext2到Ext4,找数据的方式发生了变化,但是,磁盘的布局还是非常相似的。其实这个东西也不需要变化,因为现在也没什么特别巧妙的方式,而且磁盘的吞吐量、效率的瓶颈也不在这里。当然,这里排除那些根据自身文件特点设计的数据库,毕竟还是为了支持通用文件。磁盘布局如下: Boot在第一个块,放的应该是引导程序,超级块就放在了第二个块上,如果不是可以在mount的时候通过参数sb来设置。对于经常要访问(比较重要)的内容可以在每个块组中都存储(当然这是比较浪费空间的,所有有的只选择在部分),在不同的块组中访问这些内容的时候磁头移动的距离就小了。如果开启了sparse block功.. 阅读全文
posted @ 2011-10-28 10:41 GG大婶 阅读(3171) 评论(0) 推荐(1)
摘要:工厂模式就是专门负责实例化大量相同接口的类。简单的工厂模式用《head first》中的例子就要生产不同的比萨,只需要告诉工厂你要什么样的比萨,它就会给你生产出来。这样的代码如下: 想一下简单的工厂模式为我们做了什么?相当于把生成对象的这个功能分离出去,也就是解耦让代码变得简单。这样做还有一个好处就是,在别人调用这个工厂的时候,不仅能简单地返回一个对象,还可以完成一些想要的操作。把这些操作放在这里就可以强制、统一地进行了。 这样做的初衷是想让代码尽量地简单,但是现在情况可能并不怎么好,因为在一个比萨工厂中要考虑所有的情况,而且在有所改变的时候又需要修改代码。这样本金功能简单的工厂类中的... 阅读全文
posted @ 2011-10-27 16:25 GG大婶 阅读(180) 评论(0) 推荐(0)
摘要:在这个模式中把面向对象的好处得到了很好的体现。在类设计的时候可能会遇到组合爆炸的情况,比如《head first》中咖啡的例子。在不同的咖啡中添加不同调料的时候价格是不一样的,如果有10种调料,那么一杯咖啡的种类就由2^10=1024。但是我们不可能设计1024个类来做,就算做了维护起来也是很恐怖的。 装饰者模式很好的利用继承来解决了这个问题,反正都是一杯咖啡,不过是在向里面加东西而已。如果只是要求咖啡的价格用面向过程的写成for+switch就可以了。在创造类型的过程中继承给人的感觉有点像这个循环的作用。下面是一个装饰者模式的例子:interface coffee{ int co... 阅读全文
posted @ 2011-10-26 11:38 GG大婶 阅读(153) 评论(0) 推荐(0)
摘要:1、文件与其元数据Linux获取文件状态的时候会把其相关的元数据放在stat结构中,如下:struct stat { dev_t st_dev; //文件设备节点 ino_t st_ino; //ino mode_t st_mode; //文件模式 nlink_t st_nlink; //硬链接数目 uid_t st_uid; //用户ID gid_t st_gid; //组ID dev_t st_rdev; //如果是设备,设备编号 ... 阅读全文
posted @ 2011-10-19 16:18 GG大婶 阅读(1317) 评论(0) 推荐(0)
摘要:基本概念观察者模式中有最基本的两个角色:Observable和Observer。涉及到的基本操作有:Observable在Observer中订阅,要接受消息。Observable取消注册(或者Observer将其删除)。Observer有了消息之后通知Observable。总的来看还是比较简单的。Observer中保存所有的Observable,然后在需要通知的时候调用notifyObservers来实现。下面是观察者模式的类图:对于java中的观察者模式框架下面给出一个例子:import java.util.Observable;import java.util.Observer;class 阅读全文
posted @ 2011-10-17 13:58 GG大婶 阅读(253) 评论(0) 推荐(0)
摘要:1、让出处理器 Linux提供一个系统调用运行进程主动让出执行权:sched_yield。进程运行的好好的,为什么需要这个函数呢?有一种情况是用户空间线程的锁定。如果一个线程试图取得另一个线程所持有的锁,则新的线程应该让出处理器知道该锁变为可用。用户空间锁没有内核的支持,这是一个最间单、最有效率的做法。但是现在Linux线程实现引入一个使用futexes的优化解决方案。 另一个情况是在有处理器密集型程序可用周期性调用sched_yield,试图将该进程对系统的冲击减到最小。不管怎么说,如何调度程序应该是系统的事情,而不是进程自己去管。eg:int main(){ int ret, i... 阅读全文
posted @ 2011-10-17 09:55 GG大婶 阅读(1698) 评论(2) 推荐(1)
摘要:polling下面包含了实现了基于轮询策略的select调用或其他类型的I/O轮询系统调用的基类。先看抽象类AbstractPollingIoAcceptor,成员如下:public abstract class AbstractPollingIoAcceptor<T extends AbstractIoSession, H> extends AbstractIoAcceptor { private final IoProcessor<T> processor; private final boolean createdProcessor; private final 阅读全文
posted @ 2011-10-15 18:11 GG大婶 阅读(567) 评论(0) 推荐(0)
摘要:1、IoSession与底层的传输层类型无关,表示通信双端的连接。提供用户自定义属性,可以用于在过滤器和处理器之间交换用户自定义协议相关信息。每个会话都由一个Service来提供服务,同时有一个Handler负责此会话的I/O事件处理。最重要的两个方法就是read和write,这两个方法都是异步执行,如要真正完成必须在其结果上进行等待。关闭会话的方法close也是异步执行的,也就是应等待返回的CloseFuture,此外,还有另一种关闭方式closeOnFlush,它和close的区别是会先flush掉写请求队列中的请求数据,但同样是异步的。会话的读写类型是可配置的,在运行中可设置此端是否可读 阅读全文
posted @ 2011-10-14 13:20 GG大婶 阅读(22739) 评论(0) 推荐(2)
摘要:1、TransportMetadata定义了一组操作底层的元数据信息,它的一个实现是DefaultTransportMetadata,维护的信息如下: private final String providerName; private final String name; private final boolean connectionless; private final boolean fragmentation; private final Class<? extends SocketAddress> addressType; private fin... 阅读全文
posted @ 2011-10-13 17:24 GG大婶 阅读(1091) 评论(0) 推荐(0)
摘要:与进程相关的用户ID有四个:真实的、有效的、被保存的、文件系统的用户ID。真实的ID是指启动进程的用户的ID。有效用户ID是指正在运行的进程的用户ID。被保存的ID是进程最初的有效用户ID。有效用户ID最重要,是确认进程凭证期间所检查的用户ID,真实ID和被保存的ID可作为替代品。root用户可以给uid提供任何值,但是普通用户只能提供真实ID或者被保存的用户ID。下面是和各种ID相关的方法,不详细:int main(){ printf("uid:%d\n", (int)getuid()); printf("pid:%d\n", (int)getpid( 阅读全文
posted @ 2011-10-13 09:41 GG大婶 阅读(339) 评论(5) 推荐(0)
摘要:可以通过execl函数把新的程序加载到内存中,把当前进程的映像替换成新的映像。path指向程序的位置,arg是新程序的第一个参数,省略号表示数目不定的参数,但是必须以NULL结束:int execl(const char *path, const char *arg, ...);下面是该函数的一个例子,该段代码加载了ls对应的程序,ls运行结束之后返回,而不再执行main中在其后面的代码:int main(){ int ret = execl("/bin/ls","ls", NULL); if(ret == -1){ printf("调用exe 阅读全文
posted @ 2011-10-13 08:41 GG大婶 阅读(1341) 评论(1) 推荐(0)
摘要:“同步”和“异步”这两个概念强调的是I/O操作在返回之前是否需要等待某个时间,而“同步化”强调的是必须发生何种事件。比如写入操作的四种情况如下:“同步化”+“同步”:操作会等到数据被刷入磁盘后返回,比如文件以O_SYNC模式打开;“同步化”+“异步”:虽然操作会在请求插入队列的时候就返回,但是该操作会保证数据刷入磁盘“异步化”+“同步”:数据写入内核缓冲中才返回,但是该操作只会影响内核缓冲区,这是通常方式;“异步化”+“异步”:操作插入请求队列就马上返回了。为什么会需要异步I/O操作?操作的时候不想被阻塞,那么是不是可以认为I/O操作的开销为0?把插入队列、I/O提交内核、接受操作完成通知等动 阅读全文
posted @ 2011-10-12 14:34 GG大婶 阅读(1895) 评论(0) 推荐(2)
摘要:可以调用posix_fadvise函数来设置一些操作文件的方式,比如要清楚一定区域内的缓存可以使用下面代码:int main(){ int fd = open("test", O_RDWR); int ret = posix_fadvise(fd, 0, 10, POSIX_FADV_DONTNEED); printf("%d\n", ret); if(ret == -1){ printf("posix_fadvise调用失败!\n"); } close(fd); return 0;}调用该函数后内核会把所指定的范围从页面缓冲区回收, 阅读全文
posted @ 2011-10-11 20:10 GG大婶 阅读(3423) 评论(1) 推荐(0)
摘要:mmap的好处:和read、write系统调用相比不会产生无关的副本;如果不出错就不会有系统调用、操作环境切换等开销;不再需要lseek调用。mmap的坏处:内存映射总是PAGESIZE的整数倍,会浪费一定的内存;如果要映射的内容非常大的时候可能找不到连续的线性地址空间;创建并维护内核相关数据结构,这部分可能抵消双重副本节省下的开销,尤其是大型频繁访问的文件。下面是一个文件映射比较全面的例子:int main(){ //取得页大小 //int pagesize = sysconf(_SC_PAGESIZE); int pagesize = getpagesize(); ... 阅读全文
posted @ 2011-10-11 15:47 GG大婶 阅读(874) 评论(0) 推荐(0)
摘要:epoll使得时间监听器的注册与实际的事件监视工作脱钩,有三种系统调用:初始化epoll的上下文;将要查看的文件描述符加入上下文(或移除);实际执行时间等待。#include <stdio.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/uio.h>#include <sys/epoll.h>#include <m 阅读全文
posted @ 2011-10-11 13:47 GG大婶 阅读(615) 评论(0) 推荐(0)
摘要:include <stdio.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/uio.h>int main(){ int fd = open("test", O_RDWR); char *buf[] = {"abcdefg\n", "abcdefgh\n", "a 阅读全文
posted @ 2011-10-11 08:39 GG大婶 阅读(330) 评论(0) 推荐(0)
摘要:#include <stdio.h>int main(){ FILE* file; char buf[1024], ch; file = fopen("test", "r+");//打开文件 //设置缓存 setvbuf(file, buf, _IOFBF, sizeof(buf)); fgets(buf, sizeof(buf), file);//读取一整行 ch = fgetc(file);//读取单个字符 ungetc(ch, file);//把一个字符放回流中 fread(buf, 1, 5, file);//读取二进制数据 ... 阅读全文
posted @ 2011-10-10 09:14 GG大婶 阅读(252) 评论(0) 推荐(0)
摘要:#include <stdio.h>#include <unistd.h>#include <sys/poll.h>int main(void){ //要等待的文件的数组 struct pollfd fds[2]; int ret; fds[0].fd = STDIN_FILENO;//文件符 fds[0].events = POLLIN;//等待的事件类型 fds[1].fd = STDOUT_FILENO; fds[1].events = POLLOUT; ret = poll(fds, 1, 5000); if(ret == -1){... 阅读全文
posted @ 2011-10-09 19:50 GG大婶 阅读(302) 评论(0) 推荐(1)
摘要:#include <stdio.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int main(void){ struct timeval tv; fd_set readfds; int ret; //等待stdin的输入 FD_ZERO(&readfds);//移除所有 FD_SET(STDIN_FILENO, &readfds);//加入分组 //FD_CLR用来移除 //设置等待时间 tv.tv_sec = 5; tv.tv_usec = 0; 阅读全文
posted @ 2011-10-09 14:26 GG大婶 阅读(278) 评论(0) 推荐(0)
摘要:1、ext2_add_link的执行过程,函数的定义如下:int ext2_add_link (struct dentry *dentry, struct inode *inode){ struct inode *dir = dentry->d_parent->d_inode;//父节点的inode const char *name = dentry->d_name.name;//目录名 int namelen = dentry->d_name.len;//名字长度 unsigned chunk_size = ext2_chunk_size(dir);//块大小 ... 阅读全文
posted @ 2011-10-09 09:18 GG大婶 阅读(938) 评论(0) 推荐(0)