Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
struct MyType;
typedef struct MyType *MyTypeOrError;
union MyTypeOrError {
struct MyType *my_type;
ErrorCode error_code;
};
$ sudo pmap `/usr/bin/pgrep X`
7287: /etc/X11/X :0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt1 -novtswitch
0000000000400000 2032K r-x-- /usr/bin/Xorg
00000000007fb000 8K r---- /usr/bin/Xorg
00000000007fd000 48K rw--- /usr/bin/Xorg
0000000000809000 64K rw--- [ anon ]
0000000000dd3000 87424K rw--- [ anon ]
00007f6f76c5f000 4096K rw-s- [ shmid=0x3aa00022 ]
00007f6f770df000 512K rw-s- [ shmid=0x3ab4001b ]
00007f6f7715f000 384K rw-s- [ shmid=0x3a9b001e ]
00007f6f771bf000 1072K rw-s- [ shmid=0x3a9a801f ]
00007f6f772cb000 384K rw-s- [ shmid=0x3a99001d ]
00007f6f7732b000 8476K rw-s- [ shmid=0x3a97001a ]
00007f6f77b72000 384K rw-s- [ shmid=0x3a8a000d ]
00007f6f77bf2000 384K rw-s- [ shmid=0x3a97801c ]
00007f6f77c52000 384K rw-s- [ shmid=0x3a900019 ]
00007f6f77cb2000 384K rw-s- [ shmid=0x3a830018 ]
00007f6f77d12000 4096K rw-s- [ shmid=0x3a828017 ]
00007f6f78112000 512K rw-s- [ shmid=0x3a820016 ]
00007f6f78192000 384K rw-s- [ shmid=0x3a808015 ]
00007f6f781f2000 384K rw-s- [ shmid=0x3a800013 ]
00007f6f78252000 384K rw-s- [ shmid=0x3a7f000e ]
00007f6f782b2000 512K rw-s- [ shmid=0x3a7b0012 ]
00007f6f78332000 384K rw-s- [ shmid=0x3a798010 ]
00007f6f783b2000 384K rw-s- [ shmid=0x3a8e8014 ]
00007f6f78412000 384K rw-s- [ shmid=0x3a7d800b ]
00007f6f78472000 384K rw-s- [ shmid=0x3a768009 ]
00007f6f784d2000 512K rw-s- [ shmid=0x3a75800c ]
00007f6f78572000 512K rw-s- [ shmid=0x3ab48021 ]
00007f6f785f2000 384K rw-s- [ shmid=0x3a94000f ]
00007f6f78652000 384K rw-s- [ shmid=0x3a73800a ]
00007f6f786b2000 384K rw-s- [ shmid=0x3a728008 ]
00007f6f78712000 512K rw-s- [ shmid=0x3a720007 ]
00007f6f78792000 9004K rw--- [ anon ]
00007f6f7905d000 384K rw-s- [ shmid=0x3a6f8006 ]
00007f6f790bd000 18008K rw--- [ anon ]
00007f6f7a253000 384K rw-s- [ shmid=0x3a6c8002 ]
00007f6f7a2b3000 48K r-x-- /usr/lib64/libnss_files-2.18.so
00007f6f7a2bf000 2044K ----- /usr/lib64/libnss_files-2.18.so
00007f6f7a4be000 4K r---- /usr/lib64/libnss_files-2.18.so
00007f6f7a4bf000 4K rw--- /usr/lib64/libnss_files-2.18.so
00007f6f7a4e1000 48K r-x-- /usr/lib64/xorg/modules/input/evdev_drv.so
00007f6f7a4ed000 2044K ----- /usr/lib64/xorg/modules/input/evdev_drv.so
00007f6f7a6ec000 4K r---- /usr/lib64/xorg/modules/input/evdev_drv.so
00007f6f7a6ed000 4K rw--- /usr/lib64/xorg/modules/input/evdev_drv.so
00007f6f7a6fe000 788K rw-s- /dev/nvidia0
00007f6f7a7c3000 8192K rw-s- /dev/nvidia0
00007f6f7afc3000 188K r-x-- /usr/lib64/xorg/modules/libwfb.so
00007f6f7aff2000 2044K ----- /usr/lib64/xorg/modules/libwfb.so
00007f6f7b1f1000 4K r---- /usr/lib64/xorg/modules/libwfb.so
00007f6f7b1f2000 4K rw--- /usr/lib64/xorg/modules/libwfb.so
00007f6f7b1f3000 144K r-x-- /usr/lib64/xorg/modules/libfb.so
00007f6f7b217000 2044K ----- /usr/lib64/xorg/modules/libfb.so
00007f6f7b416000 4K r---- /usr/lib64/xorg/modules/libfb.so
00007f6f7b417000 4K rw--- /usr/lib64/xorg/modules/libfb.so
00007f6f7b418000 7156K r-x-- /usr/lib64/nvidia-current/xorg/nvidia_drv.so
00007f6f7bb15000 2048K ----- /usr/lib64/nvidia-current/xorg/nvidia_drv.so
00007f6f7bd15000 784K rw--- /usr/lib64/nvidia-current/xorg/nvidia_drv.so
00007f6f7bdd9000 444K rw--- [ anon ]
00007f6f7be48000 28064K r-x-- /usr/lib64/nvidia-current/libnvidia-glcore.so.331.113
00007f6f7d9b0000 2044K ----- /usr/lib64/nvidia-current/libnvidia-glcore.so.331.113
00007f6f7dbaf000 10796K rwx-- /usr/lib64/nvidia-current/libnvidia-glcore.so.331.113
00007f6f7e63a000 116K rwx-- [ anon ]
00007f6f7e657000 12K r-x-- /usr/lib64/nvidia-current/tls/libnvidia-tls.so.331.113
00007f6f7e65a000 2044K ----- /usr/lib64/nvidia-current/tls/libnvidia-tls.so.331.113
00007f6f7e859000 4K rw--- /usr/lib64/nvidia-current/tls/libnvidia-tls.so.331.113
00007f6f7e85a000 9480K r-x-- /usr/lib64/nvidia-current/xorg/libglx.so.331.113
00007f6f7f19c000 2048K ----- /usr/lib64/nvidia-current/xorg/libglx.so.331.113
00007f6f7f39c000 2404K rwx-- /usr/lib64/nvidia-current/xorg/libglx.so.331.113
00007f6f7f5f5000 16K rwx-- [ anon ]
00007f6f7f5f9000 16K r-x-- /usr/lib64/xorg/modules/drivers/v4l_drv.so
00007f6f7f5fd000 2044K ----- /usr/lib64/xorg/modules/drivers/v4l_drv.so
00007f6f7f7fc000 4K r---- /usr/lib64/xorg/modules/drivers/v4l_drv.so
00007f6f7f7fd000 4K rw--- /usr/lib64/xorg/modules/drivers/v4l_drv.so
00007f6f7f7fe000 84K r-x-- /usr/lib64/libgcc_s-4.8.2.so.1
00007f6f7f813000 2044K ----- /usr/lib64/libgcc_s-4.8.2.so.1
00007f6f7fa12000 4K r---- /usr/lib64/libgcc_s-4.8.2.so.1
00007f6f7fa13000 4K rw--- /usr/lib64/libgcc_s-4.8.2.so.1
00007f6f7fa14000 404K r-x-- /usr/lib64/libpcre.so.1.2.1
00007f6f7fa79000 2044K ----- /usr/lib64/libpcre.so.1.2.1
00007f6f7fc78000 4K r---- /usr/lib64/libpcre.so.1.2.1
00007f6f7fc79000 4K rw--- /usr/lib64/libpcre.so.1.2.1
00007f6f7fc7a000 128K r-x-- /usr/lib64/libgraphite2.so.3.0.1
00007f6f7fc9a000 2044K ----- /usr/lib64/libgraphite2.so.3.0.1
00007f6f7fe99000 8K r---- /usr/lib64/libgraphite2.so.3.0.1
00007f6f7fe9b000 4K rw--- /usr/lib64/libgraphite2.so.3.0.1
00007f6f7fe9c000 1016K r-x-- /usr/lib64/libglib-2.0.so.0.3800.2
00007f6f7ff9a000 2044K ----- /usr/lib64/libglib-2.0.so.0.3800.2
00007f6f80199000 4K r---- /usr/lib64/libglib-2.0.so.0.3800.2
00007f6f8019a000 4K rw--- /usr/lib64/libglib-2.0.so.0.3800.2
00007f6f8019b000 4K rw--- [ anon ]
00007f6f8019c000 324K r-x-- /usr/lib64/libharfbuzz.so.0.922.0
00007f6f801ed000 2048K ----- /usr/lib64/libharfbuzz.so.0.922.0
00007f6f803ed000 4K r---- /usr/lib64/libharfbuzz.so.0.922.0
00007f6f803ee000 4K rw--- /usr/lib64/libharfbuzz.so.0.922.0
00007f6f803ef000 376K r-x-- /usr/lib64/libpng16.so.16.16.0
00007f6f8044d000 2044K ----- /usr/lib64/libpng16.so.16.16.0
00007f6f8064c000 4K r---- /usr/lib64/libpng16.so.16.16.0
00007f6f8064d000 4K rw--- /usr/lib64/libpng16.so.16.16.0
00007f6f8064e000 24K r-x-- /usr/lib64/libfontenc.so.1.0.0
00007f6f80654000 2044K ----- /usr/lib64/libfontenc.so.1.0.0
00007f6f80853000 4K r---- /usr/lib64/libfontenc.so.1.0.0
00007f6f80854000 4K rw--- /usr/lib64/libfontenc.so.1.0.0
00007f6f80855000 4K rw--- [ anon ]
00007f6f80856000 60K r-x-- /usr/lib64/libbz2.so.1.0.6
00007f6f80865000 2044K ----- /usr/lib64/libbz2.so.1.0.6
00007f6f80a64000 4K r---- /usr/lib64/libbz2.so.1.0.6
00007f6f80a65000 4K rw--- /usr/lib64/libbz2.so.1.0.6
00007f6f80a66000 604K r-x-- /usr/lib64/libfreetype.so.6.11.3
00007f6f80afd000 2044K ----- /usr/lib64/libfreetype.so.6.11.3
00007f6f80cfc000 24K r---- /usr/lib64/libfreetype.so.6.11.3
00007f6f80d02000 4K rw--- /usr/lib64/libfreetype.so.6.11.3
00007f6f80d03000 96K r-x-- /usr/lib64/libz.so.1.2.8
00007f6f80d1b000 2048K ----- /usr/lib64/libz.so.1.2.8
00007f6f80f1b000 4K r---- /usr/lib64/libz.so.1.2.8
00007f6f80f1c000 4K rw--- /usr/lib64/libz.so.1.2.8
00007f6f80f1d000 28K r-x-- /usr/lib64/librt-2.18.so
00007f6f80f24000 2044K ----- /usr/lib64/librt-2.18.so
00007f6f81123000 4K r---- /usr/lib64/librt-2.18.so
00007f6f81124000 4K rw--- /usr/lib64/librt-2.18.so
00007f6f81125000 1712K r-x-- /usr/lib64/libc-2.18.so
00007f6f812d1000 2044K ----- /usr/lib64/libc-2.18.so
00007f6f814d0000 16K r---- /usr/lib64/libc-2.18.so
00007f6f814d4000 8K rw--- /usr/lib64/libc-2.18.so
00007f6f814d6000 16K rw--- [ anon ]
00007f6f814da000 1032K r-x-- /usr/lib64/libm-2.18.so
00007f6f815dc000 2044K ----- /usr/lib64/libm-2.18.so
00007f6f817db000 4K r---- /usr/lib64/libm-2.18.so
00007f6f817dc000 4K rw--- /usr/lib64/libm-2.18.so
00007f6f817dd000 20K r-x-- /usr/lib64/libXdmcp.so.6.0.0
00007f6f817e2000 2044K ----- /usr/lib64/libXdmcp.so.6.0.0
00007f6f819e1000 4K r---- /usr/lib64/libXdmcp.so.6.0.0
00007f6f819e2000 4K rw--- /usr/lib64/libXdmcp.so.6.0.0
00007f6f819e3000 8K r-x-- /usr/lib64/libXau.so.6.0.0
00007f6f819e5000 2048K ----- /usr/lib64/libXau.so.6.0.0
00007f6f81be5000 4K r---- /usr/lib64/libXau.so.6.0.0
00007f6f81be6000 4K rw--- /usr/lib64/libXau.so.6.0.0
00007f6f81be7000 236K r-x-- /usr/lib64/libXfont.so.1.4.1
00007f6f81c22000 2048K ----- /usr/lib64/libXfont.so.1.4.1
00007f6f81e22000 4K r---- /usr/lib64/libXfont.so.1.4.1
00007f6f81e23000 8K rw--- /usr/lib64/libXfont.so.1.4.1
00007f6f81e25000 652K r-x-- /usr/lib64/libpixman-1.so.0.32.4
00007f6f81ec8000 2048K ----- /usr/lib64/libpixman-1.so.0.32.4
00007f6f820c8000 28K r---- /usr/lib64/libpixman-1.so.0.32.4
00007f6f820cf000 4K rw--- /usr/lib64/libpixman-1.so.0.32.4
00007f6f820d0000 44K r-x-- /usr/lib64/libdrm.so.2.4.0
00007f6f820db000 2044K ----- /usr/lib64/libdrm.so.2.4.0
00007f6f822da000 4K r---- /usr/lib64/libdrm.so.2.4.0
00007f6f822db000 4K rw--- /usr/lib64/libdrm.so.2.4.0
00007f6f822dc000 96K r-x-- /usr/lib64/libpthread-2.18.so
00007f6f822f4000 2044K ----- /usr/lib64/libpthread-2.18.so
00007f6f824f3000 4K r---- /usr/lib64/libpthread-2.18.so
00007f6f824f4000 4K rw--- /usr/lib64/libpthread-2.18.so
00007f6f824f5000 16K rw--- [ anon ]
00007f6f824f9000 32K r-x-- /usr/lib64/libpciaccess.so.0.11.1
00007f6f82501000 2044K ----- /usr/lib64/libpciaccess.so.0.11.1
00007f6f82700000 4K r---- /usr/lib64/libpciaccess.so.0.11.1
00007f6f82701000 4K rw--- /usr/lib64/libpciaccess.so.0.11.1
00007f6f82702000 12K r-x-- /usr/lib64/libdl-2.18.so
00007f6f82705000 2044K ----- /usr/lib64/libdl-2.18.so
00007f6f82904000 4K r---- /usr/lib64/libdl-2.18.so
00007f6f82905000 4K rw--- /usr/lib64/libdl-2.18.so
00007f6f82906000 1884K r-x-- /usr/lib64/libcrypto.so.1.0.0
00007f6f82add000 2048K ----- /usr/lib64/libcrypto.so.1.0.0
00007f6f82cdd000 104K r---- /usr/lib64/libcrypto.so.1.0.0
00007f6f82cf7000 44K rw--- /usr/lib64/libcrypto.so.1.0.0
00007f6f82d02000 16K rw--- [ anon ]
00007f6f82d06000 64K r-x-- /usr/lib64/libudev.so.1.4.0
00007f6f82d16000 2048K ----- /usr/lib64/libudev.so.1.4.0
00007f6f82f16000 4K r---- /usr/lib64/libudev.so.1.4.0
00007f6f82f17000 4K rw--- /usr/lib64/libudev.so.1.4.0
00007f6f82f18000 120K r-x-- /usr/lib64/ld-2.18.so
00007f6f82f63000 4K rw-s- /dev/nvidia0
00007f6f82f64000 4K rw-s- /dev/nvidia0
00007f6f82f65000 4K rw-s- /dev/nvidia0
00007f6f82f66000 4K rw-s- /dev/nvidia0
00007f6f82f67000 4K rw-s- /dev/nvidia0
00007f6f82f68000 4K rw-s- /dev/nvidia0
00007f6f82f69000 4K rw-s- /dev/nvidia0
00007f6f82f6a000 4K rw-s- /dev/nvidia0
00007f6f82f6b000 4K rw-s- /dev/nvidia0
00007f6f82f6c000 4K rw-s- /dev/nvidia0
00007f6f82f6d000 384K rw-s- [ shmid=0x3a6f0005 ]
00007f6f82fcd000 384K rw-s- [ shmid=0x3a6e8004 ]
00007f6f8302d000 384K rw-s- [ shmid=0x3a6e0003 ]
00007f6f8308d000 64K rw-s- /dev/nvidia0
00007f6f8309d000 128K rw-s- /dev/nvidia0
00007f6f830bd000 348K rw--- [ anon ]
00007f6f83114000 4K rw-s- /dev/nvidia0
00007f6f83115000 4K rw-s- /dev/nvidia0
00007f6f83116000 4K rw-s- /dev/nvidia0
00007f6f83117000 4K rw-s- /dev/nvidia0
00007f6f83118000 4K rw-s- /dev/nvidia0
00007f6f83119000 4K rw-s- /dev/nvidia0
00007f6f8311a000 4K rw-s- /dev/nvidia0
00007f6f8311b000 4K rw-s- /dev/nvidia0
00007f6f8311c000 4K rw-s- /dev/nvidia0
00007f6f8311d000 4K rw-s- /dev/nvidia0
00007f6f8311e000 4K rw-s- /dev/nvidia0
00007f6f8311f000 4K rw-s- /dev/nvidia0
00007f6f83120000 4K rw-s- /dev/nvidia0
00007f6f83121000 68K rw-s- /dev/nvidia0
00007f6f83132000 4K rw-s- /dev/nvidia0
00007f6f83133000 4K rw-s- /dev/nvidia0
00007f6f83134000 8K rw--- [ anon ]
00007f6f83136000 4K r---- /usr/lib64/ld-2.18.so
00007f6f83137000 4K rw--- /usr/lib64/ld-2.18.so
00007f6f83138000 4K rw--- [ anon ]
00007fff52412000 356K rw--- [ stack ]
00007fff524b9000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]Даже если при старте захватить страницу не вышло, кто-нибудь эту страницу может когда-нибудь отпустить, она станет свободной.Угу. А ещё нас всех могут захватить инопланетяне. Нет, есть, конечно, шанс, что когда вы применяете эту технологию не в программе, а в библиотеке, что ядро выделит кому-то вот прямо-таки последнюю доступную страничку, а потом этот кто-то эту страничку отпустит, но это какие-то ужасы из разряда попадания кометой прямо вам в лоб. Даже в системах, где доступны все 4GiB ядро вряд ли будет так запросто эту страницу выделять без крайней нужды (не тот регион), так что тут мы боремся уже не случайным распределением памяти, а с какими-то вредителями, которые вас пытаются обмануть. Причём эти вредители живут прямо в адресном пространстве вашего приложение и, в общем-то, могут докучать вам миллионов разных других способов.
А вы полагаетесь на то, что она вам не отдастся никогда.Если она вам не отдалась на старте процесса — то она вам не отдастся уже никогда, поверьте. С библиотеками чуть сложнее, но даже и там вероятность того, что кто-то получит эту страничку но потом-таки отдаст её вам исчезающе мала. Но если уж вам и с этой веростностью мириться не хочется — перекройте
malloc и ::operator new для вашей библиотеки.Например, в arm верхнее адресное пространство (это инфа не 100%) выделено под периферию.Это сильно зависит от семейства.
И в какой-нибудь из них верхние адреса памяти вполне могут быть задействованы под валидные данные.С какого перепугу? Ядро само решает — что и куда оно будет класть. Вариантов ровно два: либа эта страничка занята обычной памятью — и тогда просто ядро потеряет 4K этой памяти, чтобы валидные объекты там не образовывались, либо там какая-нибудь хитрая хрень — и тогда обычные объекты там точно быть размещены не могут. В обоих случаях всё гарантированно работает.
Тем более, что err выделяется обычно или в стеке, где занимает (даже с учетом теоретически возможной «нехватки» регистров процессора) никак не 4кб, или это вообще 1 ячейка на поток.Тут вопрос не в экономии на ячейках памяти, а в количестве использованных регистров.
Утверждается, что трюк позволяет убыстрить и(или) уменьшить размер в памяти. Но это лишь абстрактные слова, а где численные оценки достигнутого эффекта для разных архитектур?А с этим у подобных трюков всегда беда. Понятно, что когда их придумывали (20 лет назад!), то скорость таки меряли. Но с тех пор и процессоры изменились и компиляторы стали умнее — а померить заново ничего нельзя: уж слишком много на этот подход теперь завязано!
А как часто случается, что регистров не хватает? Неизвестно. Это предмет для исследовательской работы.Угу. Проблема в том, что эта самая «исследовательская работа» случилась через много лет после появления Linux'а. Когда Linux появился GCC более-менее сносно себя вёл на m68k (у которого 8 обычных регистров и ещё 7 адресных, которые тоже могут участвовать во многих арифметических операциях), а на x86 он очень любил всё складывать в стек.
для них сначала выделяют память через kmalloc, который не должен выделять адреса из пространства, зарезервированного под коды ошибок, так как сам возвращает коды ошибок из этого диапазона — круг замкнулся
bool error(int code); //всегда возвращает false
bool success(); // всегда возвращает true
int lastError();
bool SomeClass::doSomething()
{
if(something_wrong)
return error(something_wrong_code);
if(something_happened)
return error(something_happened_code)
do_something();
return success();
}
Понимаю так: abi — это интерфейс, а не реализацияЭто, я извиняюсь, как? ABI — это ABI. Читаете документацию, там всё написано — на каких регистрах передаются аргументы, что, куда, и когда сохраняется. Это только в мире DOS разработчики могли сами себе ABI придумывать.
В каждом компиляторе своя реализация.Не в компиляторе, а в операционной системе.
Плюс еще есть оптимизация и прагмы, которыми можно настроить компиляцию.Прагмы могут влиять на ABI, оптимизации — разумеется, нет. Как вы результат компиляции собиратесь из нескольких модулей собирать, если вы в результате оптимизации испортили конвенцию о вызовах?
Измерять экономию памяти — скучно. Там и так ясно, что экономии или нет, или мало.Ну уж нет. Мало того, что стек ядра за 20 лет не изменился (как был 4KiB-8KiB, так и остался), так ещё и L1 кеш процессора вырос всего-то в четыре раза за эти 20 лет (16K в PowerPC 603 в 1994м, 64K в Inte Broadwell в 2014м). Тут, извините, закон Мура не действует. От слова «совсем».
Вообще-то, компилятор должен начать использовать стек только если не хватает регистров, или если в функции берется адрес переменной.Вы вообще не с той стороны смотрите. Проблема не в вызываемой функции, а в вызывающей. При описанном подходе все переменные чинно приходят через регистры (если использовать
regparm… и да, ядро его использует) и значение возвращается тоже через регистр. А вот если пытаться вернуть два значения отдельно, то в вызывающей функции вам так или иначе нужно будет положить одну из переменных на стек — со всеми вытекающими. Не забудьте про то, что у ядра стек — всего-то 4K на всех. Дополнительная память, подо всё это задействованная, тоже ляжет на кеш. Причём тут есть ещё вот какая особенность: ядро ведь использует тот же самый кеш, что и программы (у процессора он всего один), но работает-то оно куда меньше (если у вас вдруг ядро грузит систему на 99%, то у вас случилась паталогия и вам уже ничего не поможет), так что каждый байт, который оно оттуда вытесняет куда весомее, чем в случае обычных программ (концепция микроядра на этом погорела).errno в TLS, конечно, но эта концепция появилась лет через десять после описываемого трюка. И она всё равно решает только часть проблем: обращение к памяти пусть даже в L1 — это 4 такта, к регистру — 1 такт.long longи возвращаются, в принципе можно было указатель и код ошибки запаковать в long long, но с этим проблем почти столько же, сколько с описанным в статье трюком, а эффективность и переносимость ничуть не выше.Потому что возврата двух переменных ABI не предусматривает
почему в вызывающую функцию нельзя возвратить два значения в двух регистрах
Об одном трюке для возврата кода ошибки из функции