how to use the function copyout()

Scott Long scottl at
Mon Jul 25 23:42:38 GMT 2005

Felix-KM wrote:

> I can't understand how to use the function copyout().
> It is necessary to write the data from a device driver to the
> array defined in user program.
> I do it this way:
> #define IOCTL_GET_B    _IOWR("F", 127, 0x4)

What you've declared here is an ioctl that will copy in 4 bytes of
user data on entry, and copy out 4 bytes back out on exit.  The argument
that you supply to the ioctl(2) must be a pointer to a 4 byte word that
you want to copy.  This probably isn't what you want.  Based on your
code snippets, you want:

#define IOCTL_GET_B	_IOW("F", 127, unsigned short)

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)
	unsigned short data;

	case IOCTL_GET_B:
		*(unsigned short *)arg = data;

Similar code will work for all integral types, as well as simple
structures.  The generic ioctl layer will handle all of the copying
magic for you.  Copying compound structures (ones that have pointers
to other data that you also want to copy) require explicit copyin
or copyout operations on the pointers that are embedded into the
struct.  Likewise, copying arbitrary data that isn't a structure or
integral type (like an array) also requires an explicit copy operation.
You could do something like the following:

struct mysubdata {
	int foo;
	int bar;

struct mystruct {
	struct mysubdata *msd;

#define IOCTL_SET_COMPOUNT_STRUCT	_IOR("F", 123, struct mystruct)
#define IOCTL_SET_BIGDATA		_IO("F", 124")

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)
	struct mystruct *ms;
	struct mysubdata msd;
	char *bigdata *bd;


		ms = *(struct mystruct *)arg;
		copyin(ms->msd, &msd, sizeof(struct mysubdata));
		bd = malloc(65536, M_DEVBUF, M_WAITOK);
		copyin(arg, bd, 65536);

Note that the BIGDATA ioctl doesn't copy in anything on its own.  For
ioctls like this, it's often convenient to pass a structure anyway that
contains the size of the data to be copied in and a pointer to the data,
like so:

struct mybigdata {
	int	datasize;
	char	*bigdata;

#define IOCTL_SET_BIGDATA		_IOR("B", 123, struct mybigdata)

		mbd = *(struct mybigdata *)arg;
		bd = malloc(mbd->datasize, M_DEVBUF, M_WAITOK);
		copyin(mbd->bigdata, bd, mbd->datasize);

Does this make sense?  Fell free to contact me with questions on this or
anything else.


More information about the freebsd-hackers mailing list