任何人都可以解释malloc()
内部如何运作
我有时会这样做strace program
,我看到很多sbrk
系统调用,正在man sbrk
讨论它的使用情况,malloc()
但不多.
我想了解使用dup2
和dup
.
从手册页:
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.
The two descriptors do not share the close-on-exec flag, however.
dup uses the lowest-numbered …
Run Code Online (Sandbox Code Playgroud) 我想写一个信号处理程序来捕获SIGSEGV.我使用保护内存块进行读写
char *buffer;
char *p;
char a;
int pagesize = 4096;
mprotect(buffer,pagesize,PROT_NONE)
Run Code Online (Sandbox Code Playgroud)
这可以保护从缓冲区开始的内存大小字节的内存,防止任何读取或写入.
其次,我尝试读取内存:
p = buffer;
a = *p
Run Code Online (Sandbox Code Playgroud)
这将生成一个SIGSEGV,我的处理程序将被调用.到现在为止还挺好.我的问题是,一旦调用处理程序,我想通过这样做来改变内存的访问写入
mprotect(buffer,pagesize,PROT_READ);
Run Code Online (Sandbox Code Playgroud)
并继续正常运行我的代码.我不想退出该功能.在将来写入相同内存时,我想再次捕获信号并修改写入权限,然后记录该事件.
这是代码:
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
char *buffer;
int flag=0;
static void handler(int sig, siginfo_t *si, void *unused)
{
printf("Got SIGSEGV at address: 0x%lx\n",(long) si->si_addr);
printf("Implements the handler only\n");
flag=1;
//exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{ …
Run Code Online (Sandbox Code Playgroud) Linux编程接口在第3章中有一个练习,如下所示:
当使用Linux特有重新启动()系统调用来重新启动系统,第二个参数,magic2,必须被指定为一组幻数(例如,LINUX_REBOOT_MAGIC2)中的一个.这些数字有什么意义?(将它们转换为十六进制提供了线索.)
该手册页告诉我们magic2
可以LINUX_REBOOT_MAGIC2(672274793),LINUX_REBOOT_MAGIC2A(85072278),LINUX_REBOOT_MAGIC2B(369367448),或LINUX_REBOOT_MAGIC2C(537993216)之一.我没能用十六进制解读它们的含义.我也看了一下/usr/include/linux/reboot.h
,也没有给出任何有用的评论.
然后我在内核的源代码中搜索了它sys_reboot
的定义.我发现的只是头文件中的声明.
因此,我的第一个问题是,这些数字有什么意义?我的第二个问题是,在哪里sys_reboot
定义,你是如何找到它的?
编辑:我在中找到了定义kernel/sys.c
.我只是贪图sys_reboot
,忘了grep的MAGIC数字.我认为定义必须隐藏在一些宏技巧背后,所以我查看了下面的System.map
文件/boot
,并在旁边找到它ctrl_alt_del
.然后我抓住那个符号,这导致我找到了正确的文件.如果我从源代码编译内核,我可以尝试找到定义符号的对象文件,并从那里开始.
我可以使用什么来调用操作系统在用户默认的任何浏览器中打开URL?不担心跨操作系统兼容性; 如果它在linux中工作对我来说足够了!
我可以理解如何编写一个使用多个进程或线程的程序:fork()一个新进程并使用IPC,或创建多个线程并使用这些通信机制.
我也理解上下文切换.也就是说,只有一次CPU,操作系统为每个进程安排时间(并且有大量的调度算法),从而我们实现了同时运行多个进程.
现在我们拥有多核处理器(或多处理器计算机),我们可以在两个独立的核心上同时运行两个进程.
我的问题是关于最后一个场景:内核如何控制进程运行的核心?哪些系统调用(在Linux,甚至是Windows中)在特定核心上安排进程?
我问的原因是:我正在为学校开展一个项目,我们将在那里探索最近的计算主题 - 我选择了多核架构.关于如何在这种环境中编程(如何监视死锁或竞争条件)似乎有很多材料,但在控制各个核心本身方面却没有太多.我希望能够编写一些演示程序并提供一些汇编指令或C代码,以实现"看,我在第二个内核上运行无限循环,查看该特定内核的 CPU利用率峰值" .
任何代码示例?还是教程?
编辑:为了澄清 - 很多人都说这是操作系统的目的,应该让操作系统处理这个问题.我完全同意!但那时我所要求的(或试图感受到)是操作系统实际上做的事情.不是调度算法,而是"一旦选择了核心,必须执行哪些指令才能让核心开始获取指令?"
我研究Linux内核并发现,对于int 0x80
体系结构,中断syscall
不能用于调用系统调用.
问题是:在int 0x80
架构的情况下什么是更可取的int 0x80
或syscall
为什么?
编辑:我使用内核3.4
据我所知,用户可以拥有一个进程,每个进程都有一个地址空间(包含有效的内存位置,这个进程可以参考).我知道进程可以调用系统调用并将参数传递给它,就像任何其他库函数一样.这似乎表明所有系统调用都是通过共享内存等进入进程地址空间.但也许,这只是一个错觉,因为在高级编程语言中,系统调用看起来像任何其他函数,当进程叫它.
但是,现在让我更进一步,更深入地分析引擎盖下发生的事情.编译器如何编译系统调用?它可能会将进程提供的系统调用名称和参数压入堆栈,然后将汇编指令说成"TRAP"或其他东西 - 基本上是用于调用软件中断的汇编指令.
该TRAP汇编指令由硬件执行,首先将模式位从用户切换到内核,然后将代码指针设置为说明中断服务程序的开始.从这一点开始,ISR在内核模式下执行,从堆栈中获取参数(这是可能的,因为内核可以访问任何内存位置,甚至是用户进程拥有的内存位置)并执行系统调用end放弃CPU,再次切换模式位,用户进程从停止的位置开始.
我的理解是否正确?
附上我理解的粗略图:
compiler-construction operating-system process interrupt system-calls
我正在使用以下C代码:
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int file=0;
if((file=open("testfile.txt",O_RDONLY)) < -1)
return 1;
char buffer[19];
if(read(file,buffer,19) != 19) return 1;
printf("%s\n",buffer);
if(lseek(file,10,SEEK_SET) < 0) return 1;
if(read(file,buffer,19) != 19) return 1;
printf("%s\n",buffer);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译后会产生警告:
warning: incompatible implicit declaration of built-in
function ‘printf’ [enabled by default]
Run Code Online (Sandbox Code Playgroud)
它是什么意思,我如何安抚C编译器不引发警告?