In hook_menu(), you define a menu array, which is an associative array. The keys are Drupal paths (with a twist; see the wildcard page for more), the values are menu entries. One menu entry is again an associative array. A typical entry is:
$items['node/%node'] = array(
'title' => 'View',
'page callback' => 'node_page_view',
'page arguments' => array(1),
'access callback' => 'node_access',
'access arguments' => array('view', 1),
'type' => MENU_CALLBACK,
The menu builder collects these, applies inheritance rules and saves each entry in its row in the menu tables.
When you open a page, the system will generate the ancestors of the given path and ask the database for the menu entry of the ancestor that best fits this path. Then it calls the access callback to determine access. If it's given, it then hands over execution to the page callback.
The system determines that it has not found a path if no item can be retrieved from the database or if the node can not be loaded. (See dynamic argument replacements.) Access denied is solely determined by the access callback/arguments.
The page callback function must return a non-NULL value, if any output is to be displayed in the browser for a given URL. If the function returns no value or a NULL value, Drupal will only render the content created by drupal_page_footer (which in turn is the content created by the hook_exit implementation of all the modules.)