根据Martin Fowler撰写的论文,控制反转是程序控制流程被颠倒的原则:代替程序员控制程序流程,外部源(框架,服务,其他组件)控制它.这就像我们把东西塞进别的东西.他提到了一个关于EJB 2.0的例子:
例如,会话Bean接口定义ejbRemove,ejbPassivate(存储到辅助存储)和ejbActivate(从被动状态恢复).你无法控制何时调用这些方法,只是它们的作用.容器打电话给我们,我们不打电话给它.
这导致框架和库之间的区别:
控制反转是使框架与库不同的关键部分.库本质上是一组可以调用的函数,这些日子通常组织成类.每个调用都会执行一些操作并将控制权返回给客户端.
我认为,DI是IOC的观点,意味着对象的依赖性被颠倒了:相反,它控制着自己的依赖关系,生命周期......还有其他东西为你做.但是,正如你用手告诉我的DI,DI不一定是IOC.我们仍然可以有DI而没有IOC.
然而,在本文中(来自pococapsule,另一个IOC C/C++框架),它表明,由于IOC和DI,IOC容器和DI框架远远优于J2EE,因为J2EE将框架代码混合到组件中因此不能成为普通的旧Java/C++对象(POJO/POCO).
除依赖注入模式之外的控制容器的反转(存档链接)
附加阅读以了解旧的基于组件的开发框架的问题是什么,这导致了上面的第二篇论文:为什么以及什么是控制反转(存档链接)
我的问题:IOC和DI究竟是什么?我很迷惑.基于pococapsule,IOC比仅仅反转对象或程序员和框架之间的控制更重要.
从sys.c第123行:
void *sys_call_table[__NR_syscalls] =
{
[0 ... __NR_syscalls-1] = sys_ni_syscall,
#include <asm/unistd.h>
};
Run Code Online (Sandbox Code Playgroud)
sys_call_table
是一个指向数组的通用指针,我可以看到.但是符号是什么:
[0 ... __NR_syscalls-1]
Run Code Online (Sandbox Code Playgroud)
什么是...
?
编辑:
我在这里学到了另一个C技巧:#include <asm/unistd.h>
将被预处理并替换为其内容并分配给[0 ... _NR_syscalls-1]
.
因此,对于其原因typedef
:ED原始数据类型是抽象低级别表示,并使其更容易理解(uint64_t
而不是long long
类型,这是8个字节).
但是,有uint_fast32_t
与之相同typedef
的uint32_t
.使用"快速"版本会使程序更快吗?
据我所知,initrd
充当块设备,因此需要文件系统驱动程序(如ext2
).内核必须至少有一个用于检测文件系统的内置模块initrd
.在本文中,介绍了初始RAM磁盘的新模型initramfs,它写成:
但是由于缓存,ramdisks实际上浪费了更多的内存.Linux旨在缓存从块设备读取或写入的所有文件和目录条目,因此Linux将数据复制到ramdisk和从"ramdisk"复制到"页面缓存"(用于文件数据)和"dentry cache"(用于目录条目) .假装是块设备的ramdisk的缺点是它被视为块设备.
什么page cache
和dentry cache
?在段落中,是否意味着数据被复制,因为ramdisk
被视为块设备,因此所有数据都被缓存?
相反,ramfs
:
几年前,Linus Torvalds有一个很好的想法:如果Linux的缓存可以像文件系统一样挂载怎么办?只是将文件保存在缓存中,永远不要删除它们,直到它们被删除或系统重新启动?Linus在缓存周围写了一个名为"ramfs"的小包装器,其他内核开发人员创建了一个名为"tmpfs"的改进版本(它可以将数据写入交换空间,并限制给定挂载点的大小,以便在消耗之前填满所有可用的内存).Initramfs是tmpfs的一个实例.
这些基于ram的文件系统会自动增长或缩小以适应它们包含的数据大小.将文件添加到ramfs(或扩展现有文件)会自动分配更多内存,删除或截断文件会释放该内存.块设备和缓存之间没有重复,因为没有块设备.缓存中的副本是数据的唯一副本.最重要的是,这不是新代码,而是现有Linux缓存代码的新应用程序,这意味着它几乎不增加任何大小,非常简单,并且基于经过严格测试的基础架构.
总之,ramfs
只是文件打开并加载到内存中,不是吗?
二者initrd
并ramfs
在编译时拉链,但不同的是,initrd
被分解到由在启动内核被安装,而块设备ramfs
经由的cpio解压到存储器中.我对么?或者是ramfs
一个非常小的文件系统?
最后,直到今天,initrd
图像仍然显示在最新的内核中.然而,这initrd
实际上是ramfs
今天使用的,这个名字只是出于历史目的吗?
在构建RPM包的过程中,我必须指定BuildRoot,稍后将在%install中使用,它将调用$ RPM_BUILD_ROOT.我一直认为$ RPM_BUILD_ROOT是RPM执行打包的虚假安装.然后,在安装时使用RPM包,它将安装到实际位置.例如:
$RPM_BUILD_ROOT/usr/bin
Run Code Online (Sandbox Code Playgroud)
我认为$ RPM_BUILD_ROOT仅用于打包过程,并且在某些方面RPM可以区分$ RPM_BUILD_ROOT和实际安装位置,当用户执行"rpm -ivh package.rpm"时将是/ usr/bin.
但是最近在阅读一些文档时,建议$ RPM_BUILD_ROOT是将要安装的实际位置,并且$ RPM_BUILD_ROOT由用户使用环境变量$ RPM_BUILD_ROOT的设置指定,以便让用户在他们的愿望中安装包位置.否则,$ RPM_BUILD_ROOT将为null,它将安装到默认位置.在上面的例子中,它是/ usr/bin.因此,$ RPM_BUILD_ROOT不仅适用于打包或"虚假安装"过程,而且是用户定义安装位置的一种方式,类似于Windows中的选择文件夹位置.
我不知道我的想法是否正确.有人可以验证吗?提前致谢.
文件孔是文件中的空白空间,但不占用任何磁盘空间并包含空字节.因此,文件大小大于磁盘上的实际大小.
但是,我不知道如何创建带有文件孔的文件进行试验.
我编译的linux内核只打印消息:
CC .....
LD [M] ....
Run Code Online (Sandbox Code Playgroud)
如何隐藏由make输出的编译消息并输出我想要的内容?我在哪里可以找到在内核Makefile中执行此操作的代码部分?
我试图打印"Hello World"200,000次,它让我永远,所以我必须停下来.但是在我添加一个char数组作为缓冲区后,它花了不到10秒.为什么?
在添加缓冲区之前:
#include <iostream>
using namespace std;
int main() {
int count = 0;
std::ios_base::sync_with_stdio(false);
for(int i = 1; i < 200000; i++)
{
cout << "Hello world!\n";
count++;
}
cout<<"Count:%d\n"<<count;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是在添加缓冲区之后:
#include <iostream>
using namespace std;
int main() {
int count = 0;
std::ios_base::sync_with_stdio(false);
char buffer[1024];
cout.rdbuf()->pubsetbuf(buffer, 1024);
for(int i = 1; i < 200000; i++)
{
cout << "Hello world!\n";
count++;
}
cout<<"Count:%d\n"<<count;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这让我想起了Java.使用BufferReader读取文件有什么好处?
如何在RPM中查看这些宏的值?我可以猜测%_bindir是/ usr/bin,%_ tmppaht是/ tmp,但是我如何准确地查看它的值并且它的值是否取决于系统?
%_prefix
%_exec_prefix
%_bindir
%_sbindir
%_libexecdir
%_datadir
%_sysconfdir
%_sharedstatedir
%_localstatedir
%_libdir
%_includedir
%_oldincludedir o in
%_infodir
%_mandir
/usr
%{_prefix)
%{_exec_prefixl/bin
%{_exec_prefix}/sbin
%{_exec_prefix}/libexec
%{_prefixJ/share
%{_prefix}/etc
%{_prefixJ/com
%{_prefix}/var
%{_exec_prefix}/lib
%{_prefix}/include
/usr/include
%{_prefix}/info
%{_prefixl/man
Run Code Online (Sandbox Code Playgroud) 考虑一下这段代码:
class complex{
private:
double re, im;
public:
complex(double _re, double _im):re(_re),im(_im){}
complex(complex c):re(c.re),im(c.im){}
};
Run Code Online (Sandbox Code Playgroud)
编译时,我收到一条错误消息: invalid constructor; you probably meant ‘complex (const complex&)’
在书中C++ Programming Language
,写道:
复制构造函数定义了复制的含义 - 包括复制参数的含义 - 所以写作
complex:complex(complex c):re(c.re),im(c.im){} //错误
是一个错误,因为任何调用都会涉及无限递归.
为什么这会导致无限递归?这没有意义.