A background-job (ie. started with &) still has it's stdin, stdout and stderr connected to the terminal it was started in. It may suddenly write (eg. error-messages) to the terminal ("disturbing" the job in the foreground) or pause waiting for input from the keyboard (you must first put it in the foreground). You may of course redirect stdout and stderr to a file or to /dev/null to prevent the background-job from writing to the terminal.
A background-job can also be put in foreground - eg. the current foreground-job is stopped, and the
fg (foreground) command is used to put a background-job in the foreground. A background-job can also be reached by signals from the terminal - eg. SIGHUP when you close the terminal, which usually end (most) programs started in the terminal.
A daemon - like the ones started automatically by init.d, but which also can be started manually from a terminal - on the other hand, runs disconnected from any terminals. Even if it was manually started from a terminal, a daemon will be disconnected from the terminal, so it can neither write (stdout, stderr) nor read (stdin) it. It's also "immune" to signals sent "automatically" by the terminal. (though you can send signals to it by using
kill -signal pid).
"Background" and "foreground" refers to the process' status to some terminal - wheter it's the process currently controlling the terminal or not. Since daemons are not connected to a terminal (but has been maticousily disconnected from it in every way), it can therefor not be said to be running in the background. Daemons are just processess running without being associated with a terminal - neither in the fore-or background.
If you use
ps with the options that shows which terminal a process uses, you will see that both fore-and backgroundjobs are assosciated with a terminal (eg. tty2). Daemons on the other hand, have a "?" in this field.
Daemons usually beahaves as such, even if they're started manually. Creating a daemon of you own, is quite a bit of work - there are some trickery involved to totally disconnect it from the terminal. You should create it's own user/group to run as. You must usually use /tmp, /var/tmp or /var/run if you want it to create files - it usually shouldn't have rights anywhere else. Since it can't report errors to a terminal, you should have it write to a log-file (eg. it's own logfile in /var/log). Daemons should make an entry in /var/run with it's current PID, and should check if another instance of it was already running. It should respect locks (/var/lock) for files or devices where applicable. It should respond to SIGHUP by reloading it's config-files and use updated configurations.
Another point is how most daemons work. A daemon is usually a single executable that can run in one of two distinct modes; depending on whether it's the original daemon - the parent - started at boot or manually... or a child spawned by this parent. The parent-process usually just sits and waits for some event - a specific time, time passed, an attempt to connect to a specific network port, or what ever. When this happens, the parent creates a child-process identical to itself (using the fork() system-call) - and immediately goes back to waiting for another event (and maybe spawning more children). It's the child-process which will actually do the work - like syncing a disk, running a command (e.g.
cron) or establish a network-connection (e.g.
ftpd). The only difference between the parent and child, is that they got different PIDs and that PPID (Parent-PID) of the child is the PID of the parent-process - this can be used to determent whether the process is the parent or child. So the same process must be able to operate in two modes - as the waiting (and spawning) parent, or as a working child.
While it's not difficult to write a daemon, it's not trivial either - as you see there are quite a few "tricks" you must know first. In general, I would think writing a daemon would require a lot of effort for very little gain compared to other alternatives:
disown on a background-job is usually a good enough alternative, as it keeps the process alive even if the terminal closes. It's often a good idea to redirect stdout and stderr to a file or to /dev/null though. For more interactive programs,
screen is a good way to put something "away" until you need it.
crontab is also worth to concider.