---
name: "dev_depends"
section: "9freebsd"
platform: "linux"
package: "freebsd-manpages"
version: "12.2-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/destroy_dev/9freebsd"
---

# dev\_depends(9freebsd)

manage cdev's and DEVFS registration for devices

Part of [destroy\_dev(9freebsd)](/destroy_dev/9freebsd.md).

## NAME

**make\_dev**, **make\_dev\_cred**, **make\_dev\_credf**, **make\_dev\_p**, **make\_dev\_s**, **make\_dev\_alias**, **make\_dev\_alias\_p**, **destroy\_dev**, **destroy\_dev\_sched**, **destroy\_dev\_sched\_cb**, **destroy\_dev\_drain**, **dev\_depends** – manage *cdev*'s and DEVFS registration for devices

## SYNOPSIS

**#include \<sys/param.h\>**

**#include \<sys/conf.h\>**

*void*\

**make\_dev\_args\_init**(*struct make\_dev\_args \*args*);

*int*\

**make\_dev\_s**(*struct make\_dev\_args \*args*, *struct cdev \*\*cdev*, *const char \*fmt*, *...*);

*int*\

**make\_dev\_alias\_p**(*int flags*, *struct cdev \*\*cdev*, *struct cdev \*pdev*, *const char \*fmt*, *...*);

*void*\

**destroy\_dev**(*struct cdev \*dev*);

*void*\

**destroy\_dev\_sched**(*struct cdev \*dev*);

*void*\

**destroy\_dev\_sched\_cb**(*struct cdev \*dev*, *void (\*cb)(void \*)*, *void \*arg*);

*void*\

**destroy\_dev\_drain**(*struct cdevsw \*csw*);

*void*\

**dev\_depends**(*struct cdev \*pdev*, *struct cdev \*cdev*);

LEGACY INTERFACES

*struct* *cdev* *\**\

**make\_dev**(*struct cdevsw \*cdevsw*, *int unit*, *uid\_t uid*, *gid\_t gid*, *int perms*, *const char \*fmt*, *...*);

*struct* *cdev* *\**\

**make\_dev\_cred**(*struct cdevsw \*cdevsw*, *int unit*, *struct ucred \*cr*, *uid\_t uid*, *gid\_t gid*, *int perms*, *const char \*fmt*, *...*);

*struct* *cdev* *\**\

**make\_dev\_credf**(*int flags*, *struct cdevsw \*cdevsw*, *int unit*, *struct ucred \*cr*, *uid\_t uid*, *gid\_t gid*, *int perms*, *const char \*fmt*, *...*);

*int*\

**make\_dev\_p**(*int flags*, *struct cdev \*\*cdev*, *struct cdevsw \*devsw*, *struct ucred \*cr*, *uid\_t uid*, *gid\_t gid*, *int mode*, *const char \*fmt*, *...*);

*struct* *cdev* *\**\

**make\_dev\_alias**(*struct cdev \*pdev*, *const char \*fmt*, *...*);

## DESCRIPTION

The **make\_dev\_s**() function creates a *cdev* structure for a new device, which is returned into the *cdev* argument. It also notifies devfs(5) of the presence of the new device, that causes corresponding nodes to be created. Besides this, a [devctl(4)](/devctl/4.md) notification is sent. The function takes the structure *struct* *make\_dev\_args* *args*, which specifies the parameters for the device creation:

```
struct make_dev_args {
	size_t		 mda_size;
	int		 mda_flags;
	struct cdevsw	*mda_devsw;
	struct ucred	*mda_cr;
	uid_t		 mda_uid;
	gid_t		 mda_gid;
	int		 mda_mode;
	int		 mda_unit;
	void		*mda_si_drv1;
	void		*mda_si_drv2;
};
```

Before use and filling with the desired values, the structure must be initialized by the **make\_dev\_args\_init**() function, which ensures that future kernel interface expansion does not affect driver source code or binary interface.

The created device will be owned by *args.mda\_uid*, with the group ownership as *args.mda\_gid*. The name is the expansion of *fmt* and following arguments as [printf(9)](/printf/9.md) would print it. The name determines its path under */dev* or other devfs(5) mount point and may contain slash ‘/’ characters to denote subdirectories. The permissions of the file specified in *args.mda\_mode* are defined in ⟨sys/stat.h⟩:

```
#define S_IRWXU 0000700    /* RWX mask for owner */
#define S_IRUSR 0000400    /* R for owner */
#define S_IWUSR 0000200    /* W for owner */
#define S_IXUSR 0000100    /* X for owner */
#define S_IRWXG 0000070    /* RWX mask for group */
#define S_IRGRP 0000040    /* R for group */
#define S_IWGRP 0000020    /* W for group */
#define S_IXGRP 0000010    /* X for group */
#define S_IRWXO 0000007    /* RWX mask for other */
#define S_IROTH 0000004    /* R for other */
#define S_IWOTH 0000002    /* W for other */
#define S_IXOTH 0000001    /* X for other */
#define S_ISUID 0004000    /* set user id on execution */
#define S_ISGID 0002000    /* set group id on execution */
#define S_ISVTX 0001000    /* sticky bit */
#ifndef _POSIX_SOURCE
#define S_ISTXT 0001000
#endif
```

The *args.mda\_cr* argument specifies credentials that will be stored in the *si\_cred* member of the initialized *struct*, *cdev*.

The *args.mda\_flags* argument alters the operation of **make\_dev\_s.**() The following values are currently accepted:

- MAKEDEV\_REF

  reference the created device

- MAKEDEV\_NOWAIT

  do not sleep, the call may fail

- MAKEDEV\_WAITOK

  allow the function to sleep to satisfy malloc

- MAKEDEV\_ETERNAL

  created device will be never destroyed

- MAKEDEV\_CHECKNAME

  return an error if the device name is invalid or already exists

Only MAKEDEV\_NOWAIT, MAKEDEV\_WAITOK and MAKEDEV\_CHECKNAME values are accepted for the **make\_dev\_alias\_p**() function.

The MAKEDEV\_WAITOK flag is assumed if none of MAKEDEV\_WAITOK, MAKEDEV\_NOWAIT is specified.

The [dev\_clone(9)](/dev_clone/9.md) event handler shall specify MAKEDEV\_REF flag when creating a device in response to lookup, to avoid race where the device created is destroyed immediately after devfs\_lookup(9) drops his reference to cdev.

The MAKEDEV\_ETERNAL flag allows the kernel to not acquire some locks when translating system calls into the cdevsw methods calls. It is responsibility of the driver author to make sure that **destroy\_dev**() is never called on the returned cdev. For the convenience, use the MAKEDEV\_ETERNAL\_KLD flag for the code that can be compiled into kernel or loaded (and unloaded) as loadable module.

A panic will occur if the MAKEDEV\_CHECKNAME flag is not specified and the device name is invalid or already exists.

The **make\_dev\_p**() use of the form

```
struct cdev *dev;
int res;
res = make_dev_p(flags, &dev, cdevsw, cred, uid, gid, perms, name);
```

is equivalent to the code

```
struct cdev *dev;
struct make_dev_args args;
int res;
make_dev_args_init(&args);
args.mda_flags = flags;
args.mda_devsw = cdevsw;
args.mda_cred = cred;
args.mda_uid = uid;
args.mda_gid = gid;
args.mda_mode = perms;
res = make_dev_s(&args, &dev, name);
```

Similarly, the **make\_dev\_credf**() function call is equivalent to

```
	(void) make_dev_s(&args, &dev, name);
```

In other words, **make\_dev\_credf**() does not allow the caller to obtain the return value, and in kernels compiled with the *INVARIANTS* options, the function asserts that the device creation succeeded.

The **make\_dev\_cred**() function is equivalent to the call

```
make_dev_credf(0, cdevsw, unit, cr, uid, gid, perms, fmt, ...);
```

The **make\_dev**() function call is the same as

```
make_dev_credf(0, cdevsw, unit, NULL, uid, gid, perms, fmt, ...);
```

The **make\_dev\_alias\_p**() function takes the returned *cdev* from **make\_dev**() and makes another (aliased) name for this device. It is an error to call **make\_dev\_alias\_p**() prior to calling **make\_dev**().

The **make\_dev\_alias**() function is similar to **make\_dev\_alias**() but it returns the resulting aliasing *\*cdev* and may not return an error.

The *cdev* returned by **make\_dev\_s**() and **make\_dev\_alias\_p**() has two fields, *si\_drv1* and *si\_drv2*, that are available to store state. Both fields are of type *void* *\**, and can be initialized simultaneously with the *cdev* allocation by filling *args.mda\_si\_drv1* and *args.mda\_si\_drv2* members of the **make\_dev\_s**() argument structure, or filled after the *cdev* is allocated, if using legacy interfaces. In the latter case, the driver should handle the race of accessing uninitialized *si\_drv1* and *si\_drv2* itself. These are designed to replace the *unit* argument to **make\_dev**(), which can be obtained with **dev2unit**().

The **destroy\_dev**() function takes the returned *cdev* from **make\_dev**() and destroys the registration for that device. The notification is sent to [devctl(4)](/devctl/4.md) about the destruction event. Do not call **destroy\_dev**() on devices that were created with **make\_dev\_alias**().

The **dev\_depends**() function establishes a parent-child relationship between two devices. The net effect is that a **destroy\_dev**() of the parent device will also result in the destruction of the child device(s), if any exist. A device may simultaneously be a parent and a child, so it is possible to build a complete hierarchy.

The **destroy\_dev\_sched\_cb**() function schedules execution of the **destroy\_dev**() for the specified *cdev* in the safe context. After **destroy\_dev**() is finished, and if the supplied *cb* is not NULL, the callback *cb* is called, with argument *arg*. The **destroy\_dev\_sched**() function is the same as

```
destroy_dev_sched_cb(cdev, NULL, NULL);
```

The **d\_close**() driver method cannot call **destroy\_dev**() directly. Doing so causes deadlock when **destroy\_dev**() waits for all threads to leave the driver methods. Also, because **destroy\_dev**() sleeps, no non-sleepable locks may be held over the call. The **destroy\_dev\_sched**() family of functions overcome these issues.

The device driver may call the **destroy\_dev\_drain**() function to wait until all devices that have supplied *csw* as cdevsw, are destroyed. This is useful when driver knows that **destroy\_dev\_sched**() is called for all instantiated devices, but need to postpone module unload until **destroy\_dev**() is actually finished for all of them.

## RETURN VALUES

If successful, **make\_dev\_s**() and **make\_dev\_p**() will return 0, otherwise they will return an error. If successful, **make\_dev\_credf**() will return a valid *cdev* pointer, otherwise it will return NULL.

## ERRORS

The **make\_dev\_s**(), **make\_dev\_p**() and **make\_dev\_alias\_p**() calls will fail and the device will be not registered if:

- \[ENOMEM\]

  The MAKEDEV\_NOWAIT flag was specified and a memory allocation request could not be satisfied.

- \[ENAMETOOLONG\]

  The MAKEDEV\_CHECKNAME flag was specified and the provided device name is longer than SPECNAMELEN.

- \[EINVAL\]

  The MAKEDEV\_CHECKNAME flag was specified and the provided device name is empty, contains a "." or ".." path component or ends with ‘/’.

- \[EINVAL\]

  The MAKEDEV\_CHECKNAME flag was specified and the provided device name contains invalid characters.

- \[EEXIST\]

  The MAKEDEV\_CHECKNAME flag was specified and the provided device name already exists.

## SEE ALSO

[devctl(4)](/devctl/4.md), devfs(5), [dev\_clone(9)](/dev_clone/9.md)

## HISTORY

The **make\_dev**() and **destroy\_dev**() functions first appeared in FreeBSD 4.0. The function **make\_dev\_alias**() first appeared in FreeBSD 4.1. The function **dev\_depends**() first appeared in FreeBSD 5.0. The functions **make\_dev\_credf**(), **destroy\_dev\_sched**(), **destroy\_dev\_sched\_cb**() first appeared in FreeBSD 7.0. The function **make\_dev\_p**() first appeared in FreeBSD 8.2. The function **make\_dev\_s**() first appeared in FreeBSD 11.0.
