Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

The Anatomy of a macOS App

By: hoakley
4 December 2025 at 15:30

Programs running in windowing environments, applications as we used to know them, have more complicated requirements than those run from a command line. Rather than embed all the resources they require for windows, menus and the rest in a single file, Mac OS broke new ground by putting those into resources stored in the app’s resource fork.

prefsresedit

This is QuarkXPress version 4.11 from around 2000, with its resources displayed in the resource editor ResEdit. Executable code was also stored in CODE resources, and every file contained type and creator information to support the illusions created by the Finder.

Mac OS X

When Mac OS X was designed, it switched to the bundle structure inherited from NeXTSTEP. Instead of this multitude of resources, apps consisted of a hierarchy of directories containing files of executable code, and those with what had in Mac OS been supporting resources. Those app bundles came to adopt a standard form, shown below.

The bundle name has the extension .app, and contains a single directory Contents. Within that, the executable code is in the MacOS directory, which may contain both the main executable for the GUI app and any bundled command tools provided. Another directory contains Resources, including the app’s custom icon, and components of its GUI. In some apps, there’s another directory of Frameworks containing dylibs (libraries).

There are also two important files, Info.plist and PkgInfo. The latter contains the same type and creator information inherited from Classic Mac OS, and apparently isn’t mandatory although it appears universal. The information property list is essential, as it specifies the names of the executable and its icon file in Resources, the minimum version of macOS required, type declarations of the app’s documents, version numbers, and more.

When running a command tool in macOS, its Mach-O executable is launched by launchd, whose purpose is to run code. Launching an app is more demanding, although the app’s executable is still launched by launchd. Before that can happen, macOS starts the launch process using LaunchServices and RunningBoard, which rely on information obtained from Info.plist and other components in the app bundle.

macOS

This structure remained stable until the introduction of code signatures in Mac OS X 10.5 Leopard in 2007. Accommodating those added a directory named _CodeSignature containing the signature in a CodeResources file. That includes code directory hashes (CDHashes) to check the integrity of the contents of the app bundle. Apps distributed by the App Store include a store receipt in another directory, _MASReceipt. Since 2018, when Apple introduced notarization, the ‘ticket’ issued by Apple can be ‘stapled’ into the app bundle as the file CodeResources.

Many apps come with additional items that might in the past have been installed by them in their Library/Application Support folders and elsewhere, but are now included in the app bundle. These can include the following directories:

  • Library, containing folders of LaunchDaemons and LoginItems that would previously have been installed in either the main Library folder, or that in the user’s Home folder;
  • XPCServices, for executable code that the app uses to provide specific services;
  • Plugins, for some types of app extension (Appex);
  • Extensions, for other types of app extension, including app intents.

You may also come across other components, including a version.plist in Apple’s apps.

This centralisation of components in the app bundle has brought several benefits. Being self-contained, apps are easier to install and update, and cleaner to remove. Their components are less likely to go missing, and most of all they’re held within the protection of the app’s signature and notarisation, an important improvement in security.

Assembling these into a diagram shows how the anatomy of an app has grown over the last few years.

Components shown in pale yellow are either mandatory or essentially universal. Those shown in green are found in apps distributed through the App Store, while that shown in blue is the stapled notarisation ticket (optional). You will also see additional folders and components such as Automator workflows, scripts, and others.

There is no difference in structure between apps built for current Intel and Arm architectures. That’s because binaries in the MacOS folder (and executable code in other directories like Frameworks, XPCServices and Plugins) contain platform-specific code in a single Mach-O executable. Thus, an app that’s Universal and runs native on both architectures includes code for both in its single ‘fat’ code file, and they even have separate signatures stored within common files.

如何在Mac OS X上结束一个进程?

By: jane9309
24 March 2016 at 21:00

刚才看论文做笔记时Evernote突然停止响应了,本打算用Activity Monitor强制关闭,转念一想,不如学下如何用terminal强制关闭程序吧!正好有人对kill的一些写法有疑问,放上来分享一下。

1. 活动监视器(Activity Monitor)

不论是Windows还是Mac OS X,一定有任务管理器或活动监视器可以查看进程。想要强制终止一个进程很简单,只要找到想要终止的程序,然后点击左上角的八边形带×按钮即可。
Screen Shot 2016-03-24 at 20.01.48

2. Mac OS X 终端(Terminal)

在Terminal上输入命令来终止程序也很简单。分两步走:1. 拿到想要关闭的进程的ID(即PID);2. 命令此ID的进程关闭。下面展示下操作过程:

假设我想把Evernote强制关闭,首先打开Terminal,输入:
ps -A | grep Evernote
ps是“process status”的缩写,意思是“进程状态”,“ps -A”会列出所有当前正在运行的程序,如果此时直接回车,那么你会在terminal上看到一长串的进程,想要找到Evernote的PID不是很方便……
Screen Shot 2016-03-24 at 20.22.03
为了更方便找到Evernote所对应的PID,我们要对这些让人看得头晕的输出进行小小的处理。“|”是个pipeline,会把当前输出的文本(也就是上头一大串进程)输入到右边的命令中。“grep”你可以把它理解成“抓取”,它会从前面输入的文本中抓出带有想要搜索的文字的所有行。看下图,是不是很简洁?马上就知道Evernote的PID是945了(另一个是EvernoteHelper,不用理会)。
Screen Shot 2016-03-24 at 20.29.10
接下来进入正题——杀死进程!输入:
kill 945
然后……就结束了……杀进程很简单吧?
来我们复习一遍:
找PID: ps -A|grep [进程名]
杀进程:kill [PID]
======
补充:
  1. 请勿随意使用强制结束进程,这是在程序无法响应时才使用的杀招,如果文件没有保存,强制结束进程可能会让你丢失未保存内容。
  2. kill -9 [PID]”也能结束进程,9其实是SIGKILL对应的号码,自然也可以用“kill -SIGKILL [PID]”来结束。大家可以输入“kill -l”查看各种对应代码。
Screen Shot 2016-03-24 at 20.44.18

❌
❌