The software breakpoints are the most used and common to be used because of their portability. They are based on invalid, undefined or trap instructions depending on the architecture.
This way the debugger can catch the event and identify if this address is handled by a breakpoint and restore the memory and program counter to make the program flow continue properly.
[0xB7F08810]> !bp?
Usage: !bp[?|s|h|*] ([addr|-addr])
!bp [addr] add a breakpoint
!bp -[addr] remove a breakpoint
!bp* remove all breakpoints
!bps software breakpoint
!bph hardware breakpoint
To add a software breakpoint type:
[0xB7F75810]> !bp sym.main ; set breakpoint at flag 'sym.main'
[0xB7F75810]> !cont ; continue execution
[0x08048910]> !bp -sym.main ; remove breakpoint
You can directly specify which kind of breakpoint you want to use, just using the same syntax for "!bp", but using "!bps" or "!bph" to not let radare decide for you which is the better option. (or just define dbg.hwbp to true or false)