Phones and tablets (especially cheaper ones) generally don't have much storage space, and their other components are not that powerful (low memory, slow processor, etc. The Operating System that runs on them must therefore be kept to its absolute minimal size, and be heavily optimized to the very specific hardware inside.
For example, in order for Windows to support a wide range of personal computers from various manufacturers, it ships with a myriad of different drivers, some are generic to handle multiple versions of hardware (i.e. video cards or sound boards.) This way one or two (32 bit Vs. 64 bit) installation packages can be distributed by Microsoft that would be able to be installed on pretty much any compatible PC. The flip side is that this makes Windows installation huge in comparison.
On the other hand, Android at its lowest level has something called "Kernel". This is what allows the rest of the OS to communicate with RAM, screen, CPU, camera, buttons, etc., and is equivalent to drivers in Windows. See this diagram of Android software stack. Due to the above mentioned restrictions, the kernel must be tailored to perfectly match the specific device Android is to be installed on. This way its size can be kept minimal, but the downside is that it would be incompatible with another device, even from the same manufacturer, that has slightly different components.
The kernel is developed by the device's manufacturer such as Samsung, Motorola, LG, etc. Since it's based on Linux, the kernel's code is open source, but it usually contains some closed-source, proprietary code from other component manufacturers such as CPU or GPU (e.g. Qualcomm or Nvidia) in form of binary blobs. Then there is a layer of customization that manufacturers and carriers add to "stock" android, which is also usually closed-source and proprietary. Sometimes it's a couple of extra apps, but usually these customizations are more invasive in a form of a different user interface, as with Samsung's TouchWiz, or HTC's SenseUI.
When Google releases an upgrade to Android, they are changing all of the Android's software stack, including the kernel, libraries, runtime, framework, and applications. You can already see where the difficulty is in upgrading a device. Google's changes require the manufacturers to update their code for all the drivers for each specific device in the phone/tablet. If Samsung uses Qualcomm's CPU/GPU instead of their own, they will also need to wait for Qualcomm to update their binary blobs. The same goes for every other piece of circuitry: Wi-Fi, Bluetooth, cellular modem, flash memory controller, etc. Manufacturer of each of these components will need to see if Google's changes require them to modify the drivers that will be included in the kernel, so that the phone continues to work normally.
This is also the reason why an Android OS upgrade intended for a specific phone cannot be simply "flashed" onto a different one. Different phone models even from the same manufacturer will usually contain different hardware, thus needing a customized kernel.
Now consider the costs to the manufacturer to upgrade every device model they make every time Google releases an upgrade to Android. Their software engineers must review the changes in the upgraded OS, modify their code for every driver, thoroughly test their changes to ensure their changes don't break anything, and release the final code for roll-out. Now multiply this by every phone model they've released since the last Android upgrade.
Cell phone giants like Samsung or Motorola can afford this process in the name of customer satisfaction and brand loyalty, but small-time manufacturers simply don't have the resources for this. There's no incentive for them to upgrade the devices they are probably already selling at razor-thin margins in the first place.